package usecase

import (
	"context"
	"errors"
	"fmt"
	"log"
	"lune/talentscale/internal/domain"
	"lune/talentscale/internal/pkg/email"
	"lune/talentscale/internal/pkg/email/templates"
	"time"

	"github.com/google/uuid"
)

type candidateUsecase struct {
	repo     domain.CandidateRepository
	emailSvc *email.Service
}

func NewCandidateUsecase(repo domain.CandidateRepository, emailSvc *email.Service) domain.CandidateUsecase {
	return &candidateUsecase{repo: repo, emailSvc: emailSvc}
}

func (u *candidateUsecase) Create(ctx context.Context, c *domain.Candidate) error {
	c.ID = uuid.New()
	
	// Generate code if empty (C-YYYY-XXXX)
	if c.Code == "" {
		c.Code = "C-" + time.Now().Format("2006") + "-" + uuid.New().String()[:8]
	}

	if c.Status == "" {
		c.Status = "new"
	}
	c.CreatedAt = time.Now()
	c.UpdatedAt = time.Now()
	return u.repo.Create(ctx, c)
}

func (u *candidateUsecase) GetByID(ctx context.Context, id uuid.UUID, companyID uuid.UUID) (*domain.Candidate, error) {
	candidate, err := u.repo.GetByID(ctx, id, companyID)
	if err != nil {
		return nil, errors.New("candidate not found")
	}
	return candidate, nil
}

func (u *candidateUsecase) List(ctx context.Context, companyID uuid.UUID, status string, search string, limit, offset int) ([]domain.Candidate, int, error) {
	return u.repo.List(ctx, companyID, status, search, limit, offset)
}

func (u *candidateUsecase) Update(ctx context.Context, candidate *domain.Candidate) error {
	existing, err := u.repo.GetByID(ctx, candidate.ID, candidate.CompanyID)
	if err != nil {
		return errors.New("candidate not found")
	}
	
	candidate.CreatedAt = existing.CreatedAt
	candidate.UpdatedAt = time.Now()
	
	return u.repo.Update(ctx, candidate)
}

func (u *candidateUsecase) UpdateProfile(ctx context.Context, candidate *domain.Candidate) error {
	candidate.UpdatedAt = time.Now()
	return u.repo.UpdateProfile(ctx, candidate)
}

func (u *candidateUsecase) Delete(ctx context.Context, id uuid.UUID, companyID uuid.UUID) error {
	return u.repo.Delete(ctx, id, companyID)
}

func (u *candidateUsecase) BulkInvite(ctx context.Context, companyID uuid.UUID, candidates []domain.Candidate) error {
	for _, c := range candidates {
		// 1. Create candidate record
		c.CompanyID = companyID
		if err := u.Create(ctx, &c); err != nil {
			log.Printf("Failed to create candidate %s: %v", c.Email, err)
			continue
		}

		// 2. Prepare invitation email
		// Note: In real world, testURL should point to the assessment platform with a unique token
		testURL := fmt.Sprintf("https://talent.talentscale.id/assess/%s", c.ID.String())
		
		body := templates.RenderInvitation(c.Name, "Your Company", testURL)
		
		// 3. Send email async with 3 retries
		u.emailSvc.SendWithRetry(email.Payload{
			To:      []string{c.Email},
			Subject: "Invitation to TalentScale Assessment",
			Body:    body,
		}, 3)
	}
	return nil
}
