package iom

import (
	"fmt"
	"system-altrak/internal/domain"
	setModule "system-altrak/internal/modules/setting"
	"system-altrak/pkg/utils"
	"time"
)

type IOMService interface {
	CreateMemorandum(memo *domain.Memorandum) error
	GetMemorandumByID(id uint, branchID uint, role string) (*domain.Memorandum, error)
	ListMemorandums(branchID uint, role string) ([]domain.Memorandum, error)
	ExportMemorandumsExcel(branchID uint, role string) ([]byte, error)
	SynthesizePdf(id uint, branchID uint, role string) ([]byte, string, error)
	DeleteMemorandum(id uint, branchID uint, role string) error
}

type serviceImpl struct {
	repo    IOMRepository
	pdf     *utils.PdfGenerator
	setting setModule.SettingService
}

func NewService(repo IOMRepository, pdf *utils.PdfGenerator, setting ...setModule.SettingService) IOMService {
	var resolvedSetting setModule.SettingService
	if len(setting) > 0 {
		resolvedSetting = setting[0]
	}

	return &serviceImpl{
		repo:    repo,
		pdf:     pdf,
		setting: resolvedSetting,
	}
}

func (s *serviceImpl) CreateMemorandum(memo *domain.Memorandum) error {
	now := time.Now()
	year := now.Year()
	month := int(now.Month())

	seq, err := s.repo.GetNextSequence("IOM", year, month)
	if err != nil {
		return fmt.Errorf("failed to get memorandum sequence: %v", err)
	}
	if memo.Ref == "" {
		pattern := "{INC}/IOM-BJM/{ROM}/{YY}" // Default fallback
		if s.setting != nil {
			if p, err := s.setting.Get("iom_format"); err == nil && p != "" {
				pattern = p
			}
		}
		memo.Ref = utils.GenerateDocRef(pattern, seq, now)
	}
	memo.CreatedAt = now
	memo.Date = now

	return s.repo.CreateMemorandum(memo)
}

func (s *serviceImpl) GetMemorandumByID(id uint, branchID uint, role string) (*domain.Memorandum, error) {
	return s.repo.GetMemorandumByID(id, branchID, role)
}

func (s *serviceImpl) ListMemorandums(branchID uint, role string) ([]domain.Memorandum, error) {
	return s.repo.ListMemorandums(branchID, role)
}

func (s *serviceImpl) ExportMemorandumsExcel(branchID uint, role string) ([]byte, error) {
	memos, err := s.repo.ListMemorandums(branchID, role)
	if err != nil {
		return nil, err
	}

	headers := []string{"No", "Date", "Ref", "To Department", "From Department", "Subject", "Signed By", "Status"}
	rows := make([][]interface{}, len(memos))

	for i, memo := range memos {
		dateText := ""
		if !memo.Date.IsZero() {
			dateText = memo.Date.Format("02/01/2006")
		}
		rows[i] = []interface{}{
			i + 1,
			dateText,
			memo.Ref,
			memo.ToDepartment,
			memo.FromDepartment,
			memo.Subject,
			memo.SignedBy,
			memo.Status,
		}
	}

	generator := utils.NewExcelGenerator()
	return generator.CreateSimpleSheet("IOM", headers, rows)
}

func (s *serviceImpl) SynthesizePdf(id uint, branchID uint, role string) ([]byte, string, error) {
	memo, err := s.repo.GetMemorandumByID(id, branchID, role)
	if err != nil {
		return nil, "", err
	}

	helper := utils.NewExportHelper(s.pdf, s.setting)
	data := map[string]interface{}{
		"Header": map[string]interface{}{
			"Title": "INTER OFFICE MEMORANDUM",
			"Ref":   memo.Ref,
		},
		"Ref":            memo.Ref,
		"Date":           memo.CreatedAt.Format("02 January 2006"),
		"To":             memo.ToDepartment,
		"From":           memo.FromDepartment,
		"Subject":        memo.Subject,
		"Body":           memo.Body,
		"IsGeneral":      true,
		"SignatureName":  memo.SignedBy,
		"SignatureTitle": "AUTHORIZED PERSONNEL",
	}

	buf, err := helper.GenerateStandardPDF("iom/iom_pdf.html", data)
	if err != nil {
		return nil, "", err
	}

	return buf, memo.Ref, nil
}

func (s *serviceImpl) DeleteMemorandum(id uint, branchID uint, role string) error {
	return s.repo.DeleteMemorandum(id, branchID, role)
}
