import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { MemoryRouter } from "react-router-dom";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { ApiError } from "../data/live/http";
import { KEYS } from "../data/mock/keys";
import { I18nProvider } from "../i18n/I18nContext";
import type { Opportunity } from "../domain/types";
import { RadarOpportunitiesPage } from "./RadarOpportunitiesPage";

const backend = vi.hoisted(() => ({
  error: null as unknown,
  primaryCalls: [] as Array<{ id: string; productId: string; reason: string }>,
}));

function productMatch(productId: string, label: string, score: number) {
  return {
    brand_id: "b1",
    product_id: productId,
    brand_name_snapshot: "澄光品牌",
    product_label_snapshot: label,
    brand_updated_at: 10,
    product_updated_at: 11,
    product_fit_score: score,
    product_fit_band: "strong" as const,
    eligible: true,
    excluded: false,
    reasons: [
      { dimension: "pain" as const, score: 35, reason: "對應泛紅不適", candidate_excerpt: "泛紅不適", product_basis: "泛紅不適" },
      { dimension: "scenario" as const, score: 25, reason: "對應日常修護", candidate_excerpt: "日常修護", product_basis: "日常修護" },
      { dimension: "audience" as const, score: 20, reason: "對應敏感肌", candidate_excerpt: "敏感肌", product_basis: "敏感肌" },
      { dimension: "capability" as const, score: 20, reason: "對應修護能力", candidate_excerpt: "修護", product_basis: "修護" },
    ],
    risks: [],
    watch_ids: ["w1"],
    matched_terms: ["敏感肌"],
    matched_at: 12,
  };
}

function sampleOpportunity(): Opportunity {
  return {
    id: "opp-1",
    source: "threads",
    external_id: "https://www.threads.net/@seeker/post/shared-1",
    permalink: "https://www.threads.net/@seeker/post/shared-1",
    author_handle: "seeker",
    text: "敏感肌使用者求推薦：泛紅不適，想了解日常修護。",
    posted_at: Date.now() * 1e6,
    status: "qualified",
    intent_score: 90,
    intent_band: "high",
    reasons: [
      { dimension: "authenticity", score: 30, reason: "使用者求助" },
      { dimension: "intent", score: 30, reason: "明確詢問" },
      { dimension: "region", score: 10, reason: "未猜地區" },
      { dimension: "freshness", score: 15, reason: "剛發布" },
      { dimension: "fit", score: 5, reason: "有產品上下文" },
    ],
    region_match: "unknown",
    freshness_hours: 1,
    matched_terms: ["敏感肌"],
    primary_brand_id: "b1",
    primary_product_id: "p1",
    primary_product_label: "舒緩精華",
    primary_product_fit_score: 100,
    product_matches: [productMatch("p1", "舒緩精華", 100), productMatch("p2", "修護乳霜", 80)],
    created_at: Date.now() * 1e6,
    review_state: "pending",
  };
}

vi.mock("../data/DataContext", () => ({
  useRepos: (() => {
    const repos = {
      accounts: { async list() { return []; } },
      jobs: { async get(id: string) { return { id, template_type: "radar_sweep", status: "succeeded", progress_summary: "", progress_percent: 100, created_at: 1, updated_at: 1 }; } },
      scout: {
        async listBrands() { return [{ id: "b1", display_name: "澄光品牌", brief: "" }]; },
        async listProducts() {
          return [
            { id: "p1", brand_id: "b1", label: "舒緩精華", product_context: "", match_tags: [], pain_points: [], provider_capability_terms: [], provider_exclude_terms: [], created_at: 1, updated_at: 1 },
            { id: "p2", brand_id: "b1", label: "修護乳霜", product_context: "", match_tags: [], pain_points: [], provider_capability_terms: [], provider_exclude_terms: [], created_at: 1, updated_at: 1 },
          ];
        },
      },
      radar: {
        async listOpportunities() {
          if (backend.error) throw backend.error;
          return { list: [sampleOpportunity()], total: 1 };
        },
        async listWatches() {
          return { list: [], total: 0, active_count: 0, max_active: 5, profile_exists: true };
        },
        async getToday() {
          return { stats: { total: 0, high: 0, mid: 0, low: 0 }, high: [], mid: [], low: [], truncated_count: 0, last_swept_at: Date.now() * 1e6 };
        },
        async listSweeps() { return { list: [], total: 0 }; },
        async setPrimaryProduct(id: string, productId: string, reason: string) {
          backend.primaryCalls.push({ id, productId, reason });
          return { ...sampleOpportunity(), primary_product_id: productId, primary_product_overridden: true };
        },
      },
    };
    return () => repos;
  })(),
}));

function renderPage() {
  return render(
    <MemoryRouter initialEntries={["/app/radar/opportunities"]}>
      <I18nProvider><RadarOpportunitiesPage /></I18nProvider>
    </MemoryRouter>,
  );
}

beforeEach(() => {
  localStorage.setItem(KEYS.uiPrefs, JSON.stringify({ locale: "zh-TW", currency: "TWD", theme: "system" }));
  backend.error = null;
  backend.primaryCalls = [];
});

describe("多產品商機的證據與主推覆寫", () => {
  it("抽屜列出每個產品的匹配證據，並能改主推", async () => {
    renderPage();
    fireEvent.click(await screen.findByRole("button", { name: "為什麼推薦" }));

    expect(await screen.findByText("對應泛紅不適")).toBeTruthy();
    expect(screen.getAllByText(/修護乳霜/).length).toBeGreaterThan(0);

    fireEvent.change(screen.getByRole("combobox", { name: "主推產品" }), { target: { value: "p2" } });
    fireEvent.change(screen.getByRole("textbox", { name: "主推理由" }), { target: { value: "本次依證據指定" } });
    fireEvent.click(screen.getByRole("button", { name: "設定主推" }));

    await waitFor(() => expect(backend.primaryCalls).toEqual([{ id: "opp-1", productId: "p2", reason: "本次依證據指定" }]));
  });

  it("API 失敗時說出原因，不顯示成功的零結果", async () => {
    backend.error = new ApiError("服務暫時不可用", 501010, 503);
    renderPage();
    expect(await screen.findByRole("alert")).toBeTruthy();
    expect(screen.queryByText(/尚未指定主推產品/)).toBeNull();
  });
});
