package usecase

import (
	"context"
	"fmt"
	"strings"
	"testing"

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

func TestMergeFetchWatchKeepsSubscriberTerms(t *testing.T) {
	w := &domain.RadarWatch{Terms: []string{"求推薦", "泛紅"}, ExcludeTerms: []string{"抽獎"}}
	plan := &domain.QueryPlan{Groups: []domain.QueryPlanGroup{
		{Query: "換季 不適", Exclude: []string{"業配"}},
		{Query: "求推薦"},
	}}
	got := mergeFetchWatch(w, plan)
	if len(got.Terms) != 3 || got.Terms[0] != "求推薦" || got.Terms[1] != "泛紅" || got.Terms[2] != "換季 不適" {
		t.Fatalf("terms=%v want subscriber keywords first, then new plan queries", got.Terms)
	}
	if len(got.ExcludeTerms) != 2 {
		t.Fatalf("exclude=%v", got.ExcludeTerms)
	}
}

func TestMergeFetchWatchExpandsLongSubscriberTerms(t *testing.T) {
	w := &domain.RadarWatch{Terms: []string{"晚上睡覺容易口乾舌燥怎麼辦"}}
	got := mergeFetchWatch(w, nil)
	if len(got.Terms) == 0 {
		t.Fatal("long subscriber term must expand before fetch")
	}
	for _, term := range got.Terms {
		if !domain.IsThreadsSearchable(term) {
			t.Fatalf("fetch term %q is not searchable", term)
		}
	}
}

func TestHumanFetchErrorCrawlerSessionExpired(t *testing.T) {
	got := humanFetchError(fmt.Errorf(`Chrome crawler status 422: {"error":"crawler session expired"}`))
	if !strings.Contains(got, "Chrome 登入已過期") || !strings.Contains(got, "設定") {
		t.Fatalf("human message=%q", got)
	}
}

func TestFetchCandidatesKeepsTitleOnlyHits(t *testing.T) {
	svc := New(nil)
	svc.HitFetch = HitFetcherFunc(func(context.Context, int64, []string, int) ([]ThreadHit, string, error) {
		return []ThreadHit{{
			URL:   "https://www.threads.net/@a/post/xyz",
			Title: "皮膚泛紅怎麼辦",
		}}, "api", nil
	})
	// bill path: HitFetch returns api so FetchCandidates will try to bill.
	// Avoid billing by setting path after... FetchCandidates bills API path.
	// Use empty Usage so bill is a no-op if implemented that way.
	cands, _, _, err := svc.FetchCandidates(context.Background(), 1, &domain.RadarWatch{Terms: []string{"泛紅"}}, 10)
	if err != nil {
		t.Fatalf("fetch: %v", err)
	}
	if len(cands) != 1 || cands[0].Text == "" {
		t.Fatalf("title-only hit dropped: %+v err=%v", cands, err)
	}
}
