package usecase

import (
	"context"
	"fmt"
	"strings"

	"apps/backend/internal/module/radar/domain"
)

// mergeProductMatchIntoOpportunity is the in-memory decision used before a
// repository write. Same-product hits keep the first judgement/snapshot and
// only accumulate source watch IDs and matched terms.
func mergeProductMatchIntoOpportunity(o *domain.Opportunity, incoming *domain.ProductMatch) error {
	if o == nil || incoming == nil {
		return fmt.Errorf("%w: opportunity and product match required", domain.ErrValidation)
	}
	if err := incoming.ValidateForWrite(); err != nil {
		return err
	}
	for _, current := range o.ProductMatches {
		if current != nil && current.ProductID == incoming.ProductID {
			current.WatchIDs = domain.MergeMatchedTerms(current.WatchIDs, incoming.WatchIDs)
			current.MatchedTerms = domain.MergeMatchedTerms(current.MatchedTerms, incoming.MatchedTerms)
			domain.ApplyPrimaryProduct(o)
			return nil
		}
	}
	o.ProductMatches = append(o.ProductMatches, domain.CloneProductMatch(incoming))
	domain.ApplyPrimaryProduct(o)
	return nil
}

func productMatchFor(o *domain.Opportunity, productID string) *domain.ProductMatch {
	if o == nil {
		return nil
	}
	for _, match := range o.ProductMatches {
		if match != nil && match.ProductID == productID {
			return match
		}
	}
	return nil
}

// mergeExistingProductCandidate adds a new product judgement to an existing
// Opportunity without rerunning the five-question judge. Existing same-product
// matches intentionally consume no AI call.
func (s *Service) mergeExistingProductCandidate(ctx context.Context, ownerUID int64, watch *domain.RadarWatch, cand *domain.CandidatePost, existing *domain.Opportunity) (credits int, err error) {
	if watch == nil || watch.ContextMode != domain.WatchContextProduct || existing == nil {
		return 0, nil
	}
	if productMatchFor(existing, watch.ProductID) != nil {
		return 0, nil
	}
	product, err := s.LoadProductContext(ctx, ownerUID, watch.BrandID, watch.ProductID)
	if err != nil {
		return 0, err
	}
	match, credits, err := s.scoreProductFit(ctx, ownerUID, product, cand)
	if err != nil {
		return credits, err
	}
	match.WatchIDs = []string{watch.ID}
	if strings.TrimSpace(cand.MatchedTerm) != "" {
		match.MatchedTerms = []string{cand.MatchedTerm}
	}
	match.MatchedAt = domain.NowNano()
	_, err = s.Repo.MergeProductMatch(ctx, ownerUID, existing.ID, match)
	return credits, err
}
