import { fireEvent, render, screen, within } from "@testing-library/react";
import { MemoryRouter, Route, Routes } from "react-router-dom";
import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { KEYS } from "../data/mock/keys";
import { I18nProvider } from "../i18n/I18nContext";
import { DataDeletionPage } from "./DataDeletionPage";
import { HomePage } from "./HomePage";
import { PrivacyPage } from "./PrivacyPage";
import { TermsPage } from "./TermsPage";
import { ensureCatalog, translate } from "../lib/i18n/messages";
import { PLANS } from "../lib/usageMeter";

const authState = vi.hoisted(() => ({
  member: null as null | { id: string; email: string },
  loading: false,
}));

vi.mock("../auth/AuthContext", () => ({
  useAuth: () => ({
    member: authState.member,
    loading: authState.loading,
    unreachable: false,
    login: vi.fn(),
    logout: vi.fn(),
    reload: vi.fn(),
    updateProfile: vi.fn(),
  }),
}));

const t = (key: string, params?: Record<string, string | number>) =>
  translate("zh-TW", key, params);

function PublicRoutes({ initialPath }: { initialPath: string }) {
  return (
    <I18nProvider>
      <MemoryRouter initialEntries={[initialPath]}>
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/privacy" element={<PrivacyPage />} />
          <Route path="/terms" element={<TermsPage />} />
          <Route path="/data-deletion" element={<DataDeletionPage />} />
          <Route path="/login" element={<div data-testid="login-stub">login</div>} />
          <Route path="/app/today" element={<div data-testid="app-stub">app</div>} />
        </Routes>
      </MemoryRouter>
    </I18nProvider>
  );
}

function forceZhTwLocale() {
  localStorage.setItem(
    KEYS.uiPrefs,
    JSON.stringify({ locale: "zh-TW", currency: "TWD", theme: "system" }),
  );
}

const PRIVACY_SECTION_IDS = [
  "overview",
  "collect",
  "use",
  "threads",
  "share",
  "ai",
  "retention",
  "deletion",
  "rights",
  "security",
  "children",
  "contact",
  "updates",
] as const;

describe("public intro homepage", () => {
  // 切換語系的斷言會用到英文字典，動態載入需先等它到位
  beforeAll(async () => {
    await ensureCatalog("en");
  });

  beforeEach(() => {
    authState.member = null;
    authState.loading = false;
    forceZhTwLocale();
  });

  it("shows outcomes, product previews, pricing tips, and a single login path", () => {
    render(<PublicRoutes initialPath="/" />);

    const home = screen.getByTestId("public-home");
    expect(
      within(home).getByRole("heading", { level: 1, name: t("home.heroTitle") }),
    ).toBeInTheDocument();
    expect(within(home).getByText(t("home.heroLead"))).toBeInTheDocument();

    const features = within(home).getByTestId("home-features");
    expect(within(features).getByText(t("home.outcome.find.title"))).toBeInTheDocument();
    expect(within(features).getByText(t("home.outcome.reply.title"))).toBeInTheDocument();
    expect(within(features).getByText(t("home.outcome.close.title"))).toBeInTheDocument();

    const product = within(home).getByTestId("home-product");
    expect(within(product).getByText(t("home.productTitle"))).toBeInTheDocument();
    const preview = within(product).getByTestId("home-product-preview");
    expect(within(preview).getByText(t("home.preview.radar.title"))).toBeInTheDocument();
    expect(within(preview).getByText(t("home.preview.scout.title"))).toBeInTheDocument();
    expect(within(preview).getByText(t("home.preview.studio.title"))).toBeInTheDocument();
    expect(within(preview).getByText(t("home.preview.crm.title"))).toBeInTheDocument();
    expect(within(preview).getByText(t("home.preview.outbox.title"))).toBeInTheDocument();

    const pricing = within(home).getByTestId("home-pricing");
    for (const id of ["free", "starter", "pro"] as const) {
      const card = pricing.querySelector(`[data-plan="${id}"]`);
      expect(card, `missing plan card ${id}`).toBeTruthy();
      expect(card?.textContent).toContain(PLANS[id].name);
      expect(card?.textContent).toContain(String(PLANS[id].monthly_credits));
      // 方案卡不再放重複的登入／升級按鈕
      expect(within(card as HTMLElement).queryByRole("link")).toBeNull();
      // 點數可展開方案說明（hover／focus）
      const tip = within(card as HTMLElement).getByTestId(`plan-tip-${id}`);
      expect(tip).toBeInTheDocument();
      expect(tip.textContent).toMatch(/./);
    }

    // 登入只留頂欄一處
    const loginLinks = within(home).getAllByRole("link", { name: t("home.ctaLogin") });
    expect(loginLinks).toHaveLength(1);
    expect(loginLinks[0]).toHaveAttribute("href", "/login");

    expect(within(home).getByRole("link", { name: t("home.privacyLink") })).toHaveAttribute(
      "href",
      "/privacy",
    );
  });

  it("redirects authenticated members from `/` into the app", () => {
    authState.member = { id: "m1", email: "alice@example.com" };
    render(<PublicRoutes initialPath="/" />);
    expect(screen.queryByTestId("public-home")).not.toBeInTheDocument();
    expect(screen.getByTestId("app-stub")).toBeInTheDocument();
  });

  it("switches intro copy between zh-TW and en via the public locale control", () => {
    render(<PublicRoutes initialPath="/" />);
    const home = screen.getByTestId("public-home");
    const localeGroup = within(home).getByRole("group", { name: t("public.localeLabel") });
    fireEvent.click(within(localeGroup).getByRole("button", { name: translate("zh-TW", "locale.en") }));
    expect(
      within(home).getByRole("heading", {
        level: 1,
        name: translate("en", "home.heroTitle"),
      }),
    ).toBeInTheDocument();
  });
});

describe("public privacy policy page", () => {
  beforeEach(() => {
    authState.member = null;
    authState.loading = false;
    forceZhTwLocale();
  });

  it("renders multi-section privacy content without auth", () => {
    render(<PublicRoutes initialPath="/privacy" />);
    const page = screen.getByTestId("public-privacy");
    expect(within(page).getByRole("heading", { level: 1, name: t("privacy.title") })).toBeInTheDocument();
    expect(within(page).getByText(t("privacy.intro"))).toBeInTheDocument();
    for (const id of PRIVACY_SECTION_IDS) {
      const section = page.querySelector(`[data-privacy-section="${id}"]`);
      expect(section, `missing privacy section ${id}`).toBeTruthy();
      expect((section?.textContent ?? "").length).toBeGreaterThan(40);
    }
  });
});

describe("public terms and data deletion pages", () => {
  beforeEach(() => {
    authState.member = null;
    authState.loading = false;
    forceZhTwLocale();
  });

  it("renders terms of service with substantive sections without auth", () => {
    render(<PublicRoutes initialPath="/terms" />);
    const page = screen.getByTestId("public-terms");
    expect(within(page).getByRole("heading", { level: 1, name: t("terms.title") })).toBeInTheDocument();
    for (const id of [
      "acceptance",
      "service",
      "accounts",
      "threads",
      "content",
      "acceptable",
      "billing",
      "disclaimer",
      "termination",
      "contact",
    ]) {
      const section = page.querySelector(`[data-terms-section="${id}"]`);
      expect(section, `missing terms section ${id}`).toBeTruthy();
      expect((section?.textContent ?? "").length).toBeGreaterThan(40);
    }
  });

  it("renders data deletion instructions", () => {
    render(<PublicRoutes initialPath="/data-deletion" />);
    const page = screen.getByTestId("public-data-deletion");
    expect(within(page).getByRole("heading", { level: 1, name: t("deletion.title") })).toBeInTheDocument();
    const steps = page.querySelector('[data-deletion-section="steps"]');
    expect(steps?.textContent).toMatch(/Data Deletion Request|資料刪除請求/);
  });
});

describe("App routing structure (public outside RequireAuth)", () => {
  it("keeps legal routes as public siblings of `/login`, not under `/app`", async () => {
    const { readFileSync } = await import("node:fs");
    const { fileURLToPath } = await import("node:url");
    const path = await import("node:path");
    const appPath = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../App.tsx");
    const src = readFileSync(appPath, "utf8");
    expect(src).toMatch(/path=["']\/["']/);
    expect(src).toMatch(/path=["']\/privacy["']/);
    expect(src).toMatch(/HomePage/);
    const appStart = src.indexOf('path="/app"');
    const appEnd = src.indexOf('path="*"');
    const appBlock = src.slice(appStart, appEnd);
    expect(appBlock).not.toMatch(/HomePage|PrivacyPage|TermsPage|DataDeletionPage/);
  });
});
