import assert from "node:assert/strict";
import { pathToFileURL } from "node:url";
import { loginBrowser, requireOperatorPassword } from "./auth.js";

export const uiLoadsProof = Object.freeze({
  unitId: "ui-loads",
  proofId: "ui-loads-ac-01",
  criterionIds: ["AC-01"] as const,
  runtimeInputs: ["AWP_WEB_URL", "AWP_PLAYWRIGHT_MODULE", "AWP_OPERATOR_PASSWORD"] as const,
  inputSelectors: [] as const,
  scope: "Explicit /projects route and root redirect are tested independently.",
});

export interface UiLoadsEvidence {
  readonly criterionId: "AC-01";
  readonly proofId: typeof uiLoadsProof.proofId;
  readonly outcome: "passed";
  readonly projectsStatus: number;
  readonly rootStatus: number;
  readonly rootRedirect: string;
  readonly elapsedMs: number;
  readonly consoleErrors: readonly string[];
  readonly timestamp: string;
}

export async function runUiLoadsProof(
  environment: Readonly<Record<string, string | undefined>> = process.env,
): Promise<UiLoadsEvidence> {
  const webUrl = environment.AWP_WEB_URL;
  const playwrightModule = environment.AWP_PLAYWRIGHT_MODULE;
  if (!webUrl) throw new Error("AWP_WEB_URL is required");
  if (!playwrightModule) throw new Error("AWP_PLAYWRIGHT_MODULE is required");
  const operatorPassword = requireOperatorPassword(environment);

  const projectsUrl = new URL("/projects", webUrl);
  const { chromium } = await import(playwrightModule);
  const browser = await chromium.launch({ headless: true });
  try {
    const page = await browser.newPage();
    await loginBrowser(page, webUrl, operatorPassword);
    const consoleErrors: string[] = [];
    page.on("console", (message: { type(): string; text(): string }) => {
      if (message.type() === "error") consoleErrors.push(message.text());
    });
    page.on("pageerror", (error: Error) => consoleErrors.push(error.message));

    const started = performance.now();
    const projectsResponse = await page.goto(projectsUrl.href, { waitUntil: "networkidle" });
    assert.equal(projectsResponse?.status(), 200);
    await page.getByRole("heading", { name: "Projects", exact: true }).waitFor();
    const elapsedMs = performance.now() - started;
    assert.ok(elapsedMs < 3_000, `Visible Projects heading took ${Math.round(elapsedMs)}ms`);

    const rootResponse = await page.goto(new URL("/", webUrl).href, { waitUntil: "networkidle" });
    assert.equal(rootResponse?.status(), 200);
    assert.equal(new URL(page.url()).href, projectsUrl.href);
    await page.getByRole("heading", { name: "Projects", exact: true }).waitFor();
    assert.deepEqual(consoleErrors, []);

    return {
      criterionId: "AC-01",
      proofId: uiLoadsProof.proofId,
      outcome: "passed",
      projectsStatus: projectsResponse.status(),
      rootStatus: rootResponse.status(),
      rootRedirect: page.url(),
      elapsedMs: Math.round(elapsedMs),
      consoleErrors,
      timestamp: new Date().toISOString(),
    };
  } finally {
    await browser.close();
  }
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  process.stdout.write(`${JSON.stringify(await runUiLoadsProof())}\n`);
}
