package usecase_test

import (
	"context"
	"testing"

	"apps/backend/internal/module/scout/domain"
	"apps/backend/internal/module/scout/repository"
	"apps/backend/internal/module/scout/usecase"

	"github.com/stretchr/testify/require"
)

type capturedSearchProvider struct {
	terms []string
	hits  []usecase.ThreadSearchResult
}

func TestPrepareBriefPlansDeduplicatedTermsFromAllInputs(t *testing.T) {
	svc := usecase.New(repository.NewMemory())
	brand, err := svc.CreateBrand(context.Background(), 1, "B", "")
	require.NoError(t, err)
	product, err := svc.SaveProduct(context.Background(), 1, &domain.Product{
		BrandID: brand.ID, Label: "P", PainPoints: []string{"敏感肌", "敏感肌"}, MatchTags: []string{"保養", "敏感肌"},
	})
	require.NoError(t, err)
	brief, err := svc.PrepareBrief(context.Background(), 1, "敏感肌保養", brand.ID, product.ID, "value", false)
	require.NoError(t, err)
	require.Equal(t, []string{"敏感肌", "保養", "使用情境", "替代方案", "成分／規格", "敏感肌保養"}, brief.ScanTerms)
}

func (p *capturedSearchProvider) SearchThreads(_ context.Context, terms []string, _ int) ([]usecase.ThreadSearchResult, error) {
	p.terms = append([]string(nil), terms...)
	return p.hits, nil
}

func TestPlannerProductSignalsAndDeterministicPersistence(t *testing.T) {
	provider := &capturedSearchProvider{hits: []usecase.ThreadSearchResult{
		{URL: "https://www.threads.net/@a/post/1?utm_source=test", Snippet: "請問敏感肌怎麼舒緩？"},
		{URL: "https://www.threads.net/@b/post/2", Snippet: "敏感肌保養有沒有推薦？"},
		{URL: "https://www.threads.net/@c/post/3", Snippet: "敏感肌服務洽詢，現在限時優惠"},
		{URL: "https://www.threads.net/@d/post/4", Snippet: "分享敏感肌保養的使用心得"},
		{URL: "https://www.threads.net/@e/post/5", Snippet: "敏感肌抽獎，互追拿好禮"},
	}}
	store := repository.NewMemory()
	svc := usecase.New(store)
	svc.Provider = provider
	brief := &domain.RunBrief{
		Mode: domain.ModeProduct, Intent: "敏感肌保養", Pains: []string{"敏感肌", "敏感肌"},
		Tags: []string{"保養", "敏感肌"}, Periphery: []string{"使用情境", "保養"},
	}
	brief.ScanTerms = []string{"敏感肌", "保養", "使用情境", "敏感肌保養"}

	posts, err := svc.RunScanFromBrief(context.Background(), 42, brief)
	require.NoError(t, err)
	require.Equal(t, []string{"敏感肌", "保養", "使用情境", "敏感肌保養"}, provider.terms)
	require.Len(t, posts, 4)
	byClass := map[string]*domain.Post{}
	for _, post := range posts {
		byClass[post.Classification] = post
		require.NotEmpty(t, post.Permalink)
		require.Equal(t, post.Permalink, post.ExternalID)
		require.InDelta(t, 0, post.Score, 100)
		require.NotEmpty(t, post.MatchReason)
	}
	require.Contains(t, byClass, domain.ClassificationSeekingHelp)
	require.Contains(t, byClass, domain.ClassificationSeekingRecommendation)
	require.Contains(t, byClass, domain.ClassificationProviderOffer)
	require.Contains(t, byClass, domain.ClassificationDiscussion)
	require.Contains(t, byClass[domain.ClassificationSeekingHelp].MatchReason, "敏感肌")
	require.Equal(t, "https://www.threads.net/@a/post/1", byClass[domain.ClassificationSeekingHelp].Permalink)

	again, err := svc.RunScanFromBrief(context.Background(), 42, brief)
	require.NoError(t, err)
	require.Equal(t, byClass[domain.ClassificationSeekingHelp].ID, again[0].ID)
	persisted, err := svc.ListPosts(context.Background(), 42, "")
	require.NoError(t, err)
	require.Len(t, persisted, 4)
}

func TestPlannerActivityClassifiesWithNeutralRecency(t *testing.T) {
	provider := &capturedSearchProvider{hits: []usecase.ThreadSearchResult{
		{URL: "https://www.threads.net/@a/post/1", Snippet: "請問這週市集怎麼報名？"},
		{URL: "https://www.threads.net/@b/post/2", Snippet: "市集活動公告，週六開幕"},
		{URL: "https://www.threads.net/@c/post/3", Snippet: "市集攤位服務洽詢"},
		{URL: "https://www.threads.net/@d/post/4", Snippet: "分享市集逛街心得"},
		{URL: "https://www.threads.net/@e/post/5", Snippet: "市集 crypto 賺錢群組"},
	}}
	svc := usecase.New(repository.NewMemory())
	svc.Provider = provider
	brief := &domain.RunBrief{Mode: domain.ModeActivity, Intent: "市集", ScanTerms: []string{"市集"}}

	posts, err := svc.RunScanFromBrief(context.Background(), 7, brief)
	require.NoError(t, err)
	require.Len(t, posts, 4)
	classes := map[string]bool{}
	for _, post := range posts {
		classes[post.Classification] = true
		require.Contains(t, post.MatchReason, "recency unavailable (neutral)")
		require.Greater(t, post.Score, 0)
	}
	require.True(t, classes[domain.ClassificationAsking])
	require.True(t, classes[domain.ClassificationAnnouncement])
	require.True(t, classes[domain.ClassificationProviderOffer])
	require.True(t, classes[domain.ClassificationDiscussion])
}

func TestDraftOutreachIsDeterministicAndDoesNotNeedAI(t *testing.T) {
	svc := usecase.New(repository.NewMemory())
	svc.Provider = &capturedSearchProvider{hits: []usecase.ThreadSearchResult{{
		URL: "https://www.threads.net/@author/post/1", Snippet: "請問怎麼處理頭皮困擾？",
	}}}
	posts, err := svc.RunScanFromBrief(context.Background(), 9, &domain.RunBrief{
		Mode: domain.ModeTheme, Intent: "頭皮", ScanTerms: []string{"頭皮"},
	})
	require.NoError(t, err)
	draft, err := svc.DraftOutreach(context.Background(), 9, posts[0].ID, "")
	require.NoError(t, err)
	require.Equal(t, "嗨 @author，看到你提到「頭皮」，我也遇過類似情況。若你願意，想聽聽你後來怎麼處理。", draft.DraftText)
}
