import { expect, test } from "@playwright/test";
import { installMockApi } from "./mockApi";

test.beforeEach(async ({ page }) => {
  await installMockApi(page);
});

test("shell renders navigation, brand and connection status", async ({ page }) => {
  await page.goto("/");
  await expect(page.getByText("RPKI Explorer")).toBeVisible();

  const nav = page.getByRole("navigation", { name: "Primary" });
  for (const label of [
    "Overview",
    "Repositories",
    "Publication Points",
    "Objects",
    "Validation",
    "Exports",
    "Runs",
    "API",
  ]) {
    await expect(nav.getByRole("link", { name: label })).toBeVisible();
  }

  await expect(page.getByText("connected")).toBeVisible();
});

test("every nav entry navigates to a real page (no dead controls)", async ({ page }) => {
  await page.goto("/");
  const nav = page.getByRole("navigation", { name: "Primary" });

  const cases: { label: string; path: RegExp; heading: string | RegExp }[] = [
    { label: "Repositories", path: /\/repositories$/, heading: "Repositories" },
    { label: "Publication Points", path: /\/publication-points$/, heading: "Publication Points" },
    { label: "Objects", path: /\/objects$/, heading: "Objects" },
    { label: "Validation", path: /\/validation$/, heading: "Validation" },
    { label: "Exports", path: /\/exports$/, heading: "Exports" },
    { label: "Runs", path: /\/runs$/, heading: "Runs" },
    { label: "API", path: /\/api$/, heading: "API" },
  ];

  for (const { label, path, heading } of cases) {
    await nav.getByRole("link", { name: label, exact: true }).click();
    await expect(page).toHaveURL(path);
    await expect(page.getByRole("heading", { name: heading }).first()).toBeVisible();
  }
});

test("run selector pins the run via ?run= and pages use it", async ({ page }) => {
  const requests: string[] = [];
  page.on("request", (req) => {
    if (req.url().includes("/api/v1/runs/")) requests.push(req.url());
  });

  await page.goto("/");
  const selector = page.getByLabel("Run");
  await expect(selector).toBeVisible();
  await selector.selectOption("run_0001");
  await expect(page).toHaveURL(/run=run_0001/);
  await expect.poll(() => requests.some((url) => url.includes("/runs/run_0001/"))).toBe(true);
});

test("run selector polls for new runs without a page refresh", async ({ page }) => {
  test.setTimeout(60_000);
  let runsRequests = 0;
  page.on("request", (req) => {
    const url = new URL(req.url());
    if (/\/api\/v1\/runs$/.test(url.pathname)) runsRequests += 1;
  });

  await page.goto("/");
  await expect(page.getByLabel("Run")).toBeVisible();
  // Initial fetch happens immediately; the 30s refetchInterval issues another.
  await expect
    .poll(() => runsRequests, { timeout: 45_000, intervals: [1_000, 2_000, 5_000] })
    .toBeGreaterThan(1);
});

test("topbar search routes to the search page with the query", async ({ page }) => {
  await page.goto("/");
  const input = page.getByRole("searchbox", { name: "Global search" });
  await input.fill("repo-a.example");
  await input.press("Enter");
  await expect(page).toHaveURL(/\/search\?q=repo-a/);
  await expect(page.getByRole("heading", { name: "Search", exact: true })).toBeVisible();
});

test("unknown routes render the 404 page", async ({ page }) => {
  await page.goto("/definitely-not-a-page");
  await expect(page.getByText("404")).toBeVisible();
  await page.getByRole("link", { name: "Back to Overview" }).click();
  await expect(page).toHaveURL(/\/$/);
});

test("deep links restore page state after reload", async ({ page }) => {
  await page.goto("/objects?type=manifest");
  await expect(page).toHaveURL(/type=manifest/);
  await expect(page.getByLabel("Type")).toHaveValue("manifest");
  await page.reload();
  await expect(page.getByLabel("Type")).toHaveValue("manifest");
});

test("runs page lists runs, pins a run and expands artifacts", async ({ page }) => {
  await page.goto("/runs");
  // Scope to the row: the actions cell also contains the run id in its
  // accessible name ("Use run run_0002 …"), so a bare cell lookup is ambiguous.
  await expect(
    page.getByRole("row", { name: /run_0002/ }).getByRole("cell").first(),
  ).toContainText("run_0002");
  const row = page.getByRole("row", { name: /run_0001/ });
  await expect(row.getByRole("cell").first()).toContainText("run_0001");

  // Expand artifacts for run_0001
  await row.getByRole("button", { name: "Artifacts" }).click();
  await expect(page.getByText("/data/runs/run_0001/report.json")).toBeVisible();

  // Pin run_0001 — navigates to overview with ?run=run_0001
  await row.getByRole("button", { name: "Use run" }).click();
  await expect(page).toHaveURL(/run=run_0001/);
});
