const fs = require("node:fs");
const path = require("node:path");

const { expect, test } = require("@playwright/test");

const evidence = path.resolve(__dirname, "../../docs/evidence/stage-13");
test.beforeAll(() => fs.mkdirSync(evidence, { recursive: true }));

async function authenticate(page) {
  await page.goto("/");
  await page.getByLabel("账号名").fill("stage13admin");
  await page.getByLabel("密码").fill("Stage13-pass-123!");
  await page.getByRole("button", { name: "登录", exact: true }).click();
  await expect(page.locator(".sidebar, .field-error")).toBeVisible();
  if (!(await page.locator(".sidebar").isVisible())) {
    await page.getByRole("tab", { name: "注册" }).click();
    await page.getByRole("button", { name: "注册并登录" }).click();
    await expect(page.locator(".sidebar")).toBeVisible();
  }
}

function summary() {
  return {
    context: { requested_date: "2026-07-30", actual_date: "2026-07-30", previous_date: "2026-07-29", observed_at: "2026-07-30T15:00:00+08:00", state: "final", carried_forward: false, message: "" },
    values: { temperature: 42, limit_up: 68, limit_down: 4, broken: 24, seal_rate: 73.9, amount: 1628000000000 },
  };
}

function pool() {
  const items = Array.from({ length: 4 }, (_, index) => ({
    identifier: `00000${index + 1}.SZ`, code: `00000${index + 1}`, name: `移动样本${index + 1}`,
    streak: index + 1, change: 9.9, price: 10 + index, sector: "机器人",
    first_time: "09:35", last_time: "14:20", open_times: index, turnover_rate: 8 + index,
    amount: 300000000, seal_amount: 50000000, reason: "产业链催化与资金承接",
  }));
  return { trade_date: "2026-07-30", observed_at: "2026-07-30T15:00:00+08:00", carried_forward: false, message: "", overview: { up_count: 2960, down_count: 1980, flat_count: 112, limit_up: 68, limit_down: 4, broken: 24, seal_rate: 73.9, amount: 1628000000000 }, items };
}

async function mockMarket(page) {
  await page.route("**/api/market/summary", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify(summary()) }));
  await page.route("**/api/review/alerts?*", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify({ items: [], unread_count: 0, as_of: "2026-07-30" }) }));
  await page.route("**/api/market/workspaces/*", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify(pool()) }));
}

async function assertViewport(page, width, height) {
  await page.setViewportSize({ width, height });
  await expect(page.getByLabel("切换行情页面")).toBeVisible();
  const metrics = await page.evaluate(() => {
    const visible = (element) => {
      const style = getComputedStyle(element);
      const rect = element.getBoundingClientRect();
      return style.visibility !== "hidden" && style.display !== "none" && rect.width > 0 && rect.height > 0;
    };
    const undersized = [...document.querySelectorAll("button")]
      .filter(visible)
      .map((element) => ({ label: element.getAttribute("aria-label") || element.textContent.trim(), rect: element.getBoundingClientRect() }))
      .filter((item) => item.rect.width < 43.5 || item.rect.height < 43.5)
      .map((item) => item.label);
    return { overflow: document.documentElement.scrollWidth - innerWidth, undersized };
  });
  expect(metrics.overflow).toBeLessThanOrEqual(0);
  expect(metrics.undersized).toEqual([]);
}

test("mobile information architecture, touch targets and responsive tables", async ({ page }) => {
  const consoleErrors = [];
  page.on("console", (message) => { if (message.type() === "error" && !message.text().includes("401 (Unauthorized)")) consoleErrors.push(message.text()); });
  await mockMarket(page);
  await authenticate(page);
  await page.setViewportSize({ width: 320, height: 568 });
  await page.getByLabel("切换行情页面").selectOption("pool");
  await expect(page.getByRole("heading", { name: "涨停池" })).toBeVisible();
  await expect(page.locator(".mobile-date-control .date-input")).toHaveValue("2026-07-30");
  await expect(page.getByRole("navigation", { name: "移动端主导航" }).getByText("行情", { exact: true })).toHaveAttribute("aria-current", "page");
  await expect(page.locator(".data-table tbody tr")).toHaveCount(4);
  await expect(page.locator(".data-table tbody td").filter({ hasText: "移动样本1" })).toHaveAttribute("data-label", "股票");
  expect(await page.locator(".data-table tbody tr").first().evaluate((row) => row.scrollWidth <= row.clientWidth)).toBe(true);

  await page.evaluate(() => window.scrollTo(0, document.documentElement.scrollHeight));
  expect(await page.evaluate(() => window.scrollY)).toBeGreaterThan(0);
  await page.getByRole("navigation", { name: "移动端主导航" }).getByRole("link", { name: "选股" }).click();
  await expect(page).toHaveURL(/\/workspace\/screener$/);
  await expect.poll(() => page.evaluate(() => window.scrollY)).toBe(0);
  await page.getByRole("navigation", { name: "移动端主导航" }).getByRole("link", { name: "行情" }).click();
  await page.getByLabel("切换行情页面").selectOption("pool");

  for (const viewport of [[320, 568], [375, 667], [390, 844], [430, 932], [768, 1024], [844, 390]]) {
    await assertViewport(page, viewport[0], viewport[1]);
  }
  for (const viewport of [[1024, 768], [1280, 720], [1440, 900], [1536, 864], [1920, 1080], [3840, 2160]]) {
    await page.setViewportSize({ width: viewport[0], height: viewport[1] });
    await expect(page.getByLabel("切换行情页面")).toBeHidden();
    expect(await page.evaluate(() => document.documentElement.scrollWidth - innerWidth)).toBeLessThanOrEqual(0);
  }
  await page.setViewportSize({ width: 320, height: 568 });
  await page.screenshot({ path: path.join(evidence, "pool-light-320x568.jpg"), type: "jpeg", quality: 82 });
  await page.getByRole("button", { name: "夜间" }).click();
  await page.setViewportSize({ width: 844, height: 390 });
  await page.screenshot({ path: path.join(evidence, "pool-dark-landscape-844x390.jpg"), type: "jpeg", quality: 82 });
  expect(consoleErrors).toEqual([]);
});

test("keyboard focus, dialog return and reduced motion remain available", async ({ page }) => {
  await mockMarket(page);
  await page.emulateMedia({ reducedMotion: "reduce" });
  await authenticate(page);
  await page.setViewportSize({ width: 390, height: 844 });
  await page.keyboard.press("Tab");
  await expect(page.getByRole("link", { name: "跳到主要内容" })).toBeFocused();
  await page.keyboard.press("Enter");
  await expect(page.locator("#main-content")).toBeFocused();
  const search = page.getByRole("button", { name: "全局搜索" });
  await search.focus();
  await search.click();
  await expect(page.getByRole("dialog", { name: "全局搜索" })).toBeVisible();
  await page.keyboard.press("Escape");
  await expect(search).toBeFocused();
  await expect(page.locator(".emotion-dot")).toHaveCSS("animation-duration", "0.001s");
});

test("all sixteen workspaces remain reachable without page overflow", async ({ page }) => {
  await page.route("**/api/market/summary", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify(summary()) }));
  await page.route("**/api/review/alerts?*", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify({ items: [], unread_count: 0, as_of: "2026-07-30" }) }));
  await page.route("**/api/market/workspaces/*", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify({ trade_date: "", message: "移动端空态验收" }) }));
  await page.route("**/api/market/insights/*", (route) => route.fulfill({ contentType: "application/json", body: JSON.stringify({ trade_date: "", message: "移动端空态验收" }) }));
  await authenticate(page);
  await page.setViewportSize({ width: 320, height: 568 });
  const keys = ["emotion", "pool", "broken", "limit-down", "yesterday", "performance", "ladder", "rotation", "auction", "themes", "popularity", "dragon-list", "screener", "mentor", "heaven", "review"];
  for (const key of keys) {
    await page.goto(`/workspace/${key}`);
    await expect(page.locator(".page-frame")).toBeVisible();
    expect(await page.evaluate(() => document.documentElement.scrollWidth - innerWidth), key).toBeLessThanOrEqual(0);
    await expect(page.locator(".mobile-date-control .date-input")).toBeVisible();
    if (key === "review") {
      await expect(page.getByRole("button", { name: "提醒中心" })).toBeVisible();
      await expect(page.getByRole("button", { name: "复盘助手" })).toBeVisible();
    }
  }
});
