// internal/services/verification_service.go
package services

import (
	"encoding/json"
	"errors"
	"lost-and-found/internal/models"
	"lost-and-found/internal/repositories"
	"lost-and-found/internal/utils"
	"strconv" 

	"gorm.io/gorm"
)

type VerificationService struct {
	verificationRepo *repositories.ClaimVerificationRepository
	claimRepo        *repositories.ClaimRepository
	itemRepo         *repositories.ItemRepository
	lostItemRepo     *repositories.LostItemRepository // ✅ TAMBAHAN: Untuk Direct Claim
}

func NewVerificationService(db *gorm.DB) *VerificationService {
	return &VerificationService{
		verificationRepo: repositories.NewClaimVerificationRepository(db),
		claimRepo:        repositories.NewClaimRepository(db),
		itemRepo:         repositories.NewItemRepository(db),
		lostItemRepo:     repositories.NewLostItemRepository(db), // ✅ TAMBAHAN
	}
}

// VerificationResult represents the verification result
type VerificationResult struct {
	SimilarityScore float64           `json:"similarity_score"`
	MatchLevel      string            `json:"match_level"`
	MatchedKeywords []string          `json:"matched_keywords"`
	Details         map[string]string `json:"details"`
	Recommendation  string            `json:"recommendation"`
}

// VerifyClaimDescription verifies claim description against item/lost_item description
func (s *VerificationService) VerifyClaimDescription(claimID uint) (*VerificationResult, error) {
	// 1. Get Claim
	claim, err := s.claimRepo.FindByID(claimID)
	if err != nil {
		return nil, err
	}

	var targetDescription string
	var sourceName string

	// 2. Tentukan Target Deskripsi (Regular vs Direct Claim)
	if claim.ItemID != nil {
		// --- REGULAR CLAIM (Barang Temuan) ---
		item, err := s.itemRepo.FindByID(*claim.ItemID) // ✅ Dereference pointer
		if err != nil {
			return nil, err
		}
		
		// Bandingkan dengan Secret Details (prioritas) atau Description
		targetDescription = item.SecretDetails
		if targetDescription == "" {
			targetDescription = item.Description
		}
		sourceName = "item_secret_details"

	} else if claim.LostItemID != nil {
		// --- DIRECT CLAIM (Barang Hilang) ---
		lostItem, err := s.lostItemRepo.FindByID(*claim.LostItemID) // ✅ Dereference pointer
		if err != nil {
			return nil, err
		}
		
		// Untuk direct claim, deskripsi Finder (Claim) dibandingkan dengan deskripsi Owner (LostItem)
		targetDescription = lostItem.Description
		sourceName = "lost_item_description"

	} else {
		return nil, errors.New("invalid claim: no item or lost_item attached")
	}

	// 3. Calculate similarity
	similarity := utils.CalculateStringSimilarity(claim.Description, targetDescription)
	similarityPercent := similarity * 100

	// 4. Extract matched keywords
	claimKeywords := utils.ExtractKeywords(claim.Description)
	itemKeywords := utils.ExtractKeywords(targetDescription)
	matchedKeywords := utils.FindMatchedKeywords(claimKeywords, itemKeywords)

	// 5. Determine match level
	matchLevel := "low"
	recommendation := "REJECT - Ciri khusus tidak cocok"
	
	if similarityPercent >= 75.0 {
		matchLevel = "high"
		recommendation = "APPROVE - Ciri khusus sangat cocok"
	} else if similarityPercent >= 50.0 {
		matchLevel = "medium"
		recommendation = "REVIEW - Perlu verifikasi fisik/tanya jawab"
	}

	// 6. Create or update verification record
	verification, _ := s.verificationRepo.FindByClaimID(claimID)
	if verification == nil {
		verification = &models.ClaimVerification{
			ClaimID:         claimID,
			SimilarityScore: similarityPercent,
			MatchedKeywords: stringSliceToJSON(matchedKeywords),
			IsAutoMatched:   false,
		}
		s.verificationRepo.Create(verification)
	} else {
		verification.SimilarityScore = similarityPercent
		verification.MatchedKeywords = stringSliceToJSON(matchedKeywords)
		s.verificationRepo.Update(verification)
	}

	return &VerificationResult{
		SimilarityScore: similarityPercent,
		MatchLevel:      matchLevel,
		MatchedKeywords: matchedKeywords,
		Details: map[string]string{
			"claim_description": claim.Description,
			sourceName:          targetDescription, // Dinamis (item atau lost_item)
			"matched_count":     strconv.Itoa(len(matchedKeywords)),
		},
		Recommendation: recommendation,
	}, nil
}

// GetVerificationByClaimID gets verification data for a claim
func (s *VerificationService) GetVerificationByClaimID(claimID uint) (*models.ClaimVerification, error) {
	verification, err := s.verificationRepo.FindByClaimID(claimID)
	if err != nil {
		return nil, err
	}
	if verification == nil {
		return nil, errors.New("verification not found")
	}
	return verification, nil
}

// GetHighMatchVerifications gets all high match verifications
func (s *VerificationService) GetHighMatchVerifications() ([]models.ClaimVerificationResponse, error) {
	verifications, err := s.verificationRepo.FindHighMatches()
	if err != nil {
		return nil, err
	}

	var responses []models.ClaimVerificationResponse
	for _, v := range verifications {
		responses = append(responses, v.ToResponse())
	}

	return responses, nil
}

// CompareDescriptions provides detailed comparison between two descriptions
func (s *VerificationService) CompareDescriptions(desc1, desc2 string) map[string]interface{} {
	similarity := utils.CalculateStringSimilarity(desc1, desc2)
	
	keywords1 := utils.ExtractKeywords(desc1)
	keywords2 := utils.ExtractKeywords(desc2)
	matchedKeywords := utils.FindMatchedKeywords(keywords1, keywords2)
	
	return map[string]interface{}{
		"similarity_score":  similarity * 100,
		"description_1":     desc1,
		"description_2":     desc2,
		"keywords_1":        keywords1,
		"keywords_2":        keywords2,
		"matched_keywords":  matchedKeywords,
		"total_keywords_1":  len(keywords1),
		"total_keywords_2":  len(keywords2),
		"matched_count":     len(matchedKeywords),
	}
}

// Helper function to convert string slice to JSON
func stringSliceToJSON(slice []string) string {
	if len(slice) == 0 {
		return "[]"
	}
	data, _ := json.Marshal(slice)
	return string(data)
}