// internal/services/export_service.go
package services

import (
	"bytes"
	"fmt"
	"lost-and-found/internal/models"
	"lost-and-found/internal/repositories"
	"lost-and-found/internal/utils"
	"time"
	"log"
	"errors"

	"gorm.io/gorm"
)

type ExportService struct {
	itemRepo     *repositories.ItemRepository
	archiveRepo  *repositories.ArchiveRepository
	claimRepo    *repositories.ClaimRepository
	auditLogRepo *repositories.AuditLogRepository
}

func NewExportService(db *gorm.DB) *ExportService {
	return &ExportService{
		itemRepo:     repositories.NewItemRepository(db),
		archiveRepo:  repositories.NewArchiveRepository(db),
		claimRepo:    repositories.NewClaimRepository(db),
		auditLogRepo: repositories.NewAuditLogRepository(db),
	}
}

// ExportRequest represents export request data
type ExportRequest struct {
	Type      string     `json:"type"`       // items, archives, claims, audit_logs
	Format    string     `json:"format"`     // pdf, excel
	StartDate *time.Time `json:"start_date"`
	EndDate   *time.Time `json:"end_date"`
	Status    string     `json:"status"`
}

// ExportItemsToPDF exports items to PDF
func (s *ExportService) ExportItemsToPDF(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) {
	
	log.Printf("DEBUG: Starting PDF export - Type: %s, Status: %s", req.Type, req.Status)
    
    // Get items
    items, _, err := s.itemRepo.FindAll(1, 10000, req.Status, "", "")
    if err != nil {
        log.Printf("ERROR: Failed to fetch items: %v", err)  // ← Tambahkan ini
        return nil, err
    }

    log.Printf("DEBUG: Found %d items", len(items))

	// Filter by date range if provided
	var filteredItems []models.Item
	for _, item := range items {
		if req.StartDate != nil && item.DateFound.Before(*req.StartDate) {
			continue
		}
		if req.EndDate != nil && item.DateFound.After(*req.EndDate) {
			continue
		}
		filteredItems = append(filteredItems, item)
	}

	if len(filteredItems) == 0 {
        return nil, errors.New("no data in specified date range")
    }

	// Generate PDF
	pdf := utils.NewPDFExporter()
	pdf.AddTitle("Laporan Barang Ditemukan")
	pdf.AddSubtitle(fmt.Sprintf("Periode: %s - %s", 
		formatDate(req.StartDate), 
		formatDate(req.EndDate)))
	pdf.AddNewLine()

	// Add table
	headers := []string{"No", "Nama Barang", "Kategori", "Lokasi", "Tanggal Ditemukan", "Status"}
	var data [][]string
	for i, item := range filteredItems {
		data = append(data, []string{
			fmt.Sprintf("%d", i+1),
			item.Name,
			item.Category.Name,
			item.Location,
			item.DateFound.Format("02 Jan 2006"),
			item.Status,
		})
	}
	pdf.AddTable(headers, data)

	// Add footer
	pdf.AddNewLine()
	pdf.AddText(fmt.Sprintf("Total: %d barang", len(filteredItems)))
	pdf.AddText(fmt.Sprintf("Dicetak pada: %s", time.Now().Format("02 January 2006 15:04")))

	// Log audit
	s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil,
		fmt.Sprintf("Exported items report (PDF, %d items)", len(filteredItems)), 
		ipAddress, userAgent)

	return pdf.Output(), nil
}

// ExportItemsToExcel exports items to Excel
func (s *ExportService) ExportItemsToExcel(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) {
	// Get items
	items, _, err := s.itemRepo.FindAll(1, 10000, req.Status, "", "")
	if err != nil {
		return nil, err
	}

	// Filter by date range if provided
	var filteredItems []models.Item
	for _, item := range items {
		if req.StartDate != nil && item.DateFound.Before(*req.StartDate) {
			continue
		}
		if req.EndDate != nil && item.DateFound.After(*req.EndDate) {
			continue
		}
		filteredItems = append(filteredItems, item)
	}

	// Generate Excel
	excel := utils.NewExcelExporter()
	excel.SetSheetName("Barang Ditemukan")
	
	// Add headers
	headers := []string{"No", "Nama Barang", "Kategori", "Lokasi", "Deskripsi", 
		"Tanggal Ditemukan", "Status", "Pelapor", "Kontak"}
	excel.AddRow(headers)

	// Add data
	for i, item := range filteredItems {
		excel.AddRow([]string{
			fmt.Sprintf("%d", i+1),
			item.Name,
			item.Category.Name,
			item.Location,
			item.Description,
			item.DateFound.Format("02 Jan 2006"),
			item.Status,
			item.ReporterName,
			item.ReporterContact,
		})
	}

	// Auto-size columns
	excel.AutoSizeColumns(len(headers))

	// Log audit
	s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil,
		fmt.Sprintf("Exported items report (Excel, %d items)", len(filteredItems)), 
		ipAddress, userAgent)

	return excel.Output()
}

// ExportArchivesToPDF exports archives to PDF
func (s *ExportService) ExportArchivesToPDF(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) {
	archives, _, err := s.archiveRepo.FindAll(1, 10000, "", "")
	if err != nil {
		return nil, err
	}

	// Filter by date range
	var filteredArchives []models.Archive
	for _, archive := range archives {
		if req.StartDate != nil && archive.ArchivedAt.Before(*req.StartDate) {
			continue
		}
		if req.EndDate != nil && archive.ArchivedAt.After(*req.EndDate) {
			continue
		}
		filteredArchives = append(filteredArchives, archive)
	}

	pdf := utils.NewPDFExporter()
	pdf.AddTitle("Laporan Barang yang Diarsipkan")
	pdf.AddSubtitle(fmt.Sprintf("Periode: %s - %s", 
		formatDate(req.StartDate), 
		formatDate(req.EndDate)))
	pdf.AddNewLine()

	headers := []string{"No", "Nama Barang", "Kategori", "Alasan Arsip", "Tanggal Arsip"}
	var data [][]string
	for i, archive := range filteredArchives {
		data = append(data, []string{
			fmt.Sprintf("%d", i+1),
			archive.Name,
			archive.Category.Name,
			archive.ArchivedReason,
			archive.ArchivedAt.Format("02 Jan 2006"),
		})
	}
	pdf.AddTable(headers, data)

	pdf.AddNewLine()
	pdf.AddText(fmt.Sprintf("Total: %d barang", len(filteredArchives)))

	s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil,
		fmt.Sprintf("Exported archives report (PDF, %d items)", len(filteredArchives)), 
		ipAddress, userAgent)

	return pdf.Output(), nil
}

// ExportClaimsToPDF exports claims to PDF
func (s *ExportService) ExportClaimsToPDF(req ExportRequest, userID uint, ipAddress, userAgent string) (*bytes.Buffer, error) {
	claims, _, err := s.claimRepo.FindAll(1, 10000, req.Status, nil, nil)
	if err != nil {
		return nil, err
	}

	// Filter by date range
	var filteredClaims []models.Claim
	for _, claim := range claims {
		if req.StartDate != nil && claim.CreatedAt.Before(*req.StartDate) {
			continue
		}
		if req.EndDate != nil && claim.CreatedAt.After(*req.EndDate) {
			continue
		}
		filteredClaims = append(filteredClaims, claim)
	}

	pdf := utils.NewPDFExporter()
	pdf.AddTitle("Laporan Klaim Barang")
	pdf.AddSubtitle(fmt.Sprintf("Periode: %s - %s", 
		formatDate(req.StartDate), 
		formatDate(req.EndDate)))
	pdf.AddNewLine()

	headers := []string{"No", "Barang", "Pengklaim", "Status", "Tanggal Klaim"}
	var data [][]string
	for i, claim := range filteredClaims {
		data = append(data, []string{
			fmt.Sprintf("%d", i+1),
			claim.Item.Name,
			claim.User.Name,
			claim.Status,
			claim.CreatedAt.Format("02 Jan 2006"),
		})
	}
	pdf.AddTable(headers, data)

	pdf.AddNewLine()
	pdf.AddText(fmt.Sprintf("Total: %d klaim", len(filteredClaims)))

	s.auditLogRepo.Log(&userID, models.ActionExport, "report", nil,
		fmt.Sprintf("Exported claims report (PDF, %d claims)", len(filteredClaims)), 
		ipAddress, userAgent)

	return pdf.Output(), nil
}

// Helper function to format date
func formatDate(date *time.Time) string {
	if date == nil {
		return "N/A"
	}
	return date.Format("02 Jan 2006")
}