package usecase

import (
	"context"
	"errors"
	"testing"

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

func integrationOpportunity(owner int64) *domain.Opportunity {
	return &domain.Opportunity{OwnerUID: owner, ExternalID: "threads:same", Source: domain.OppSourceThreads, Status: domain.OppQualified, IntentScore: 82, IntentBand: domain.BandHigh, RegionMatch: domain.RegionUnknown, Reasons: []domain.OpportunityReason{
		{Dimension: domain.DimAuthenticity, Score: 20, Reason: "公開個人需求"}, {Dimension: domain.DimIntent, Score: 20, Reason: "明確詢問"}, {Dimension: domain.DimRegion, Score: 10, Reason: "未知地區"}, {Dimension: domain.DimFreshness, Score: 20, Reason: "近期"}, {Dimension: domain.DimFit, Score: 12, Reason: "可處理"},
	}, MatchedTerms: []string{"需求"}}
}

func integrationMatch(id string, score int) *domain.ProductMatch {
	audience := score - 60
	if audience < 0 {
		audience = 0
	}
	if audience > 20 {
		audience = 20
	}
	return &domain.ProductMatch{BrandID: "brand-1", ProductID: id, ProductFitScore: score, ProductFitBand: domain.ProductFitBandFromScore(score), Reasons: []domain.ProductFitReason{
		{Dimension: domain.ProductFitPain, Score: 35, Reason: "痛點", CandidateExcerpt: "漏水", ProductBasis: "漏水"}, {Dimension: domain.ProductFitScenario, Score: 25, Reason: "情境", CandidateExcerpt: "找人", ProductBasis: "居家"}, {Dimension: domain.ProductFitAudience, Score: audience, Reason: "受眾", CandidateExcerpt: "家裡", ProductBasis: "家庭"}, {Dimension: domain.ProductFitCapability, Score: score - 60 - audience, Reason: "能力", CandidateExcerpt: "抓漏", ProductBasis: "抓漏"},
	}}
}

func TestProductDomainLegacyOwnerAndSingleOpportunity(t *testing.T) {
	ctx := context.Background()
	mem := repository.NewMemory()
	legacy := &domain.RadarWatch{ID: "legacy-watch", OwnerUID: 1, Terms: []string{"找人"}, Status: domain.WatchActive}
	if err := mem.SaveWatch(ctx, legacy); err != nil {
		t.Fatal(err)
	}
	gotWatch, err := mem.GetWatch(ctx, legacy.ID)
	if err != nil || gotWatch.ContextMode != domain.WatchContextGeneric {
		t.Fatalf("legacy read: %#v %v", gotWatch, err)
	}
	opportunity, err := mem.UpsertByExternalID(ctx, integrationOpportunity(1))
	if err != nil {
		t.Fatal(err)
	}
	if _, err := mem.MergeProductMatch(ctx, 2, opportunity.ID, integrationMatch("p1", 60)); !errors.Is(err, domain.ErrForbidden) {
		t.Fatalf("cross-owner match: %v", err)
	}
	if _, err := mem.MergeProductMatch(ctx, 1, opportunity.ID, integrationMatch("p1", 60)); err != nil {
		t.Fatal(err)
	}
	if _, err := mem.MergeProductMatch(ctx, 1, opportunity.ID, integrationMatch("p2", 80)); err != nil {
		t.Fatal(err)
	}
	if _, err := mem.MergeProductMatch(ctx, 1, opportunity.ID, integrationMatch("p1", 90)); err != nil {
		t.Fatal(err)
	}
	got, err := mem.GetOpportunity(ctx, opportunity.ID)
	if err != nil {
		t.Fatal(err)
	}
	if len(got.ProductMatches) != 2 || got.PrimaryProductID != "p2" {
		t.Fatalf("single opportunity or primary arbitration failed: %#v", got)
	}
	if got.ProductMatches[0].ProductLabelSnapshot != "" {
		t.Fatalf("unexpected snapshot mutation: %#v", got.ProductMatches[0])
	}
}
