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

const backend = vi.hoisted(() => ({
  accepted: [] as string[],
  reviews: [] as Array<{ id: string; patch: Record<string, unknown> }>,
  replies: [] as Array<{ id: string; variant: string }>,
  created: [] as Array<Record<string, unknown>>,
  sweeps: [] as string[],
  firstSweepTriggered: true,
  byScope: null as null | ((filter: Record<string, unknown>) => { list: Opportunity[]; total: number }),
  watches: [] as RadarWatch[],
  lastSweptAt: 0,
}));

function watch(overrides: Partial<RadarWatch> = {}): RadarWatch {
  return {
    id: "w1",
    terms: ["敏感肌"],
    exclude_terms: [],
    regions: [],
    status: "active",
    last_swept_at: backend.lastSweptAt,
    created_at: 1,
    updated_at: 1,
    ...overrides,
  } as RadarWatch;
}

function opportunity(): Opportunity {
  return {
    id: "opp-1",
    source: "threads",
    external_id: "shared-post",
    permalink: "https://www.threads.net/@buyer/post/shared-post",
    author_handle: "buyer",
    text: "台北有人推薦美甲嗎",
    posted_at: Date.now() * 1e6,
    status: "qualified",
    intent_score: 88,
    intent_band: "high",
    reasons: [],
    region_match: "unknown",
    freshness_hours: 1,
    matched_terms: ["美甲"],
    created_at: Date.now() * 1e6,
    review_state: "pending",
  };
}

vi.mock("../data/DataContext", () => ({
  // 必須回傳同一個物件：頁面的 useCallback 依賴 repos.radar，每次新物件會讓 effect 無限重跑。
  useRepos: (() => {
    const repos = {
    accounts: { async list() { return []; } },
    scout: {
      async listBrands() { return []; },
      async listProducts() { 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 };
      },
    },
    radar: {
      async listOpportunities(filter: Record<string, unknown>) {
        if (backend.byScope) return backend.byScope(filter);
        return { list: [], total: 0 };
      },
      async listWatches() {
        return {
          list: backend.watches,
          total: backend.watches.length,
          active_count: backend.watches.filter((w) => w.status === "active").length,
          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: backend.lastSweptAt };
      },
      async listSweeps() { return { list: [], total: 0 }; },
      async triggerWatchSweep(id: string) {
        backend.sweeps.push(id);
        return { job_id: `job-${id}` };
      },
      async createWatch(input: Record<string, unknown>) {
        backend.created.push(input);
        backend.watches = [watch()];
        return { id: "w1", ...input, status: "active", first_sweep_triggered: backend.firstSweepTriggered };
      },
      async acceptOpportunity(id: string) {
        backend.accepted.push(id);
        return { opportunity_id: id, contact_id: "contact-buyer", status: "accepted" };
      },
      async createReply(id: string, variant: string) {
        backend.replies.push({ id, variant });
        return { id: "r1", opportunity_id: id, variant, text: "嗨，我在台北做美甲，可以看看我的作品集嗎？", created_at: 1 };
      },
      async updateOpportunityReviewState(id: string, patch: Record<string, unknown>) {
        backend.reviews.push({ id, patch });
        return { ...opportunity(), id, review_state: patch.state } as Opportunity;
      },
    },
    };
    return () => repos;
  })(),
}));

function renderToday() {
  return render(
    <MemoryRouter initialEntries={["/app/today"]}>
      <I18nProvider><TodayPage /></I18nProvider>
    </MemoryRouter>,
  );
}

beforeEach(() => {
  localStorage.setItem(KEYS.uiPrefs, JSON.stringify({ locale: "zh-TW", currency: "TWD", theme: "system" }));
  backend.accepted = [];
  backend.reviews = [];
  backend.replies = [];
  backend.created = [];
  backend.sweeps = [];
  backend.byScope = null;
  backend.firstSweepTriggered = true;
  backend.lastSweptAt = Date.now() * 1e6;
  backend.watches = [watch()];
});

describe("今日簡化流程", () => {
  it("回他會把人加進名單，並給出名單入口", async () => {
    backend.byScope = () => ({ list: [opportunity()], total: 1 });
    vi.spyOn(window, "open").mockReturnValue(null);
    renderToday();

    fireEvent.click(await screen.findByRole("button", { name: "回他" }));

    await waitFor(() => expect(backend.accepted).toEqual(["opp-1"]));
    expect(await screen.findByText(/也幫你加進名單/)).toBeTruthy();
    expect(screen.getByRole("link", { name: "前往名單" }).getAttribute("href")).toBe("/app/crm?contact=contact-buyer");
  });

  it("自動放寬到近 7 天後看完，不會叫使用者去清一個他沒設過的篩選", async () => {
    // 只有近 7 天有待處理的，今天沒有 → 頁面會自己放寬；跳過之後就真的空了。
    backend.byScope = (filter) => {
      const cleared = backend.reviews.length > 0;
      if (!cleared && filter.time_scope === "7d" && filter.review_state === "pending") {
        return { list: [opportunity()], total: 1 };
      }
      return { list: [], total: 0 };
    };
    renderToday();
    await screen.findByText("台北有人推薦美甲嗎");

    fireEvent.click(screen.getByRole("button", { name: "先跳過" }));

    expect(await screen.findByText("今天這批看完了")).toBeTruthy();
    expect(screen.queryByRole("button", { name: "清除篩選" })).toBeNull();
  });

  it("第一組訂閱建立後說正在找，不再叫使用者按立即巡邏", async () => {
    backend.watches = [];
    backend.lastSweptAt = 0;
    renderToday();

    fireEvent.change(await screen.findByLabelText(/關鍵字/), { target: { value: "台北 美甲推薦" } });
    fireEvent.click(screen.getByRole("button", { name: "開始找客人" }));

    await waitFor(() => expect(backend.created).toHaveLength(1));
    expect(await screen.findByText("正在幫你找，大約幾分鐘")).toBeTruthy();
    expect(screen.queryByRole("button", { name: "立即巡邏" })).toBeNull();
    expect(backend.sweeps).toEqual([]);
  });

  it("想不到怎麼回時，同一頁就能拿到草稿", async () => {
    backend.byScope = () => ({ list: [opportunity()], total: 1 });
    renderToday();

    // 卡片上的入口打開抽屜；抽屜裡才真的花點數生成。
    fireEvent.click((await screen.findAllByRole("button", { name: "幫我想回覆" }))[0]);
    const drawer = await screen.findByRole("dialog");
    fireEvent.click(within(drawer).getByRole("button", { name: "幫我想回覆" }));

    await waitFor(() => expect(backend.replies).toEqual([{ id: "opp-1", variant: "public_comment" }]));
    expect(await screen.findByText(/我在台北做美甲/)).toBeTruthy();
  });

  it("留得住進階頁入口", async () => {
    backend.byScope = () => ({ list: [opportunity()], total: 1 });
    renderToday();
    const link = await screen.findByRole("link", { name: "看全部結果" });
    expect(link.getAttribute("href")).toBe("/app/radar/opportunities");
  });
});
