import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, resolve } from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";

const webRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const read = (path) => readFileSync(resolve(webRoot, path), "utf8");
const require = createRequire(import.meta.url);

function loadTsxComponent(path) {
  const typescript = require("typescript");
  const output = typescript.transpileModule(read(path), {
    compilerOptions: {
      esModuleInterop: true,
      jsx: typescript.JsxEmit.ReactJSX,
      module: typescript.ModuleKind.CommonJS,
      target: typescript.ScriptTarget.ES2020,
    },
  }).outputText;
  const loadedModule = { exports: {} };
  new Function("require", "module", "exports", output)(
    require,
    loadedModule,
    loadedModule.exports,
  );
  return loadedModule.exports;
}

const migratedPresentation = [
  "components/Layout.tsx",
  "components/PortalUi.tsx",
  "pages/index.tsx",
  "pages/jobs/[jobId].tsx",
];

test("migrated shell and job pages use reusable classes without inline presentation", () => {
  for (const path of migratedPresentation) {
    const source = read(path);
    assert.doesNotMatch(
      source,
      /\bstyle\s*=/,
      `${path} must not use inline style props`,
    );
    assert.doesNotMatch(
      source,
      /#[\da-f]{3,8}\b/i,
      `${path} must not define visual color literals`,
    );
  }
});

test("the authenticated shell keeps organization and navigation context accessible", () => {
  const layout = read("components/Layout.tsx");
  assert.match(layout, /Active organization/);
  assert.match(layout, /activeOrg\.role/);
  assert.match(layout, /aria-current=/);
  assert.match(layout, /Skip to main content/);
  assert.match(layout, /aria-label="Primary navigation"/);
  assert.match(layout, /src="\/um-trace-mark\.png"/);
  assert.doesNotMatch(layout, />\s*UL\s*</);
});

test("the portal uses the cropped UM foreground without nested icon padding", () => {
  const layout = read("components/Layout.tsx");
  const css = read("styles/global.css");
  assert.match(layout, /src="\/um-trace-mark\.png"/);
  assert.doesNotMatch(layout, /um-trace-icon\.svg/);
  assert.match(css, /\.ul-shell__brand-mark\s*\{[^}]*object-fit:\s*contain;/s);
  assert.match(css, /\.ul-shell__brand-mark\s*\{[^}]*padding:\s*0\.375rem;/s);
});

test("status presentation always combines a readable label with an icon", () => {
  const components = read("components/PortalUi.tsx");
  for (const status of [
    "OPEN",
    "IN_PROGRESS",
    "COMPLETED",
    "CANCELLED",
    "LIVE",
    "OFFLINE",
    "ERROR",
  ]) {
    assert.match(
      components,
      new RegExp(`${status}: \\{ icon: .+, label: .+, tone:`),
    );
  }
  assert.match(components, /ul-status-badge__icon/);
  assert.match(components, /aria-hidden="true"/);
});

test("status and error-state components render accessible text and semantics", () => {
  const React = require("react");
  const { renderToStaticMarkup } = require("react-dom/server");
  const { PageState, StatusBadge } = loadTsxComponent(
    "components/PortalUi.tsx",
  );

  const status = renderToStaticMarkup(
    React.createElement(StatusBadge, { status: "IN_PROGRESS" }),
  );
  assert.match(status, />In progress</);
  assert.match(status, /ul-status-badge--warning/);
  assert.match(status, /aria-hidden="true"/);

  const error = renderToStaticMarkup(
    React.createElement(PageState, {
      kind: "error",
      title: "Jobs could not be loaded",
    }),
  );
  assert.match(error, /role="alert"/);
  assert.match(error, /Jobs could not be loaded/);
});

test("responsive, focus, touch-target, and reduced-motion rules are present", () => {
  const css = read("styles/global.css");
  assert.ok(css.startsWith('@import "./tokens.css";'));
  for (const token of [
    "--ul-color-canvas",
    "--ul-color-primary",
    "--ul-color-map",
    "--ul-touch-minimum",
    "--ul-type-family-sans",
  ]) {
    assert.match(css, new RegExp(`var\\(${token}\\)`));
  }
  assert.match(css, /:focus-visible/);
  assert.match(css, /min-height:\s*var\(--ul-touch-minimum\)/);
  assert.match(css, /@media \(max-width: 1200px\)/);
  assert.match(css, /@media \(max-width: 900px\)/);
  assert.match(css, /@media \(max-width: 600px\)/);
  assert.match(css, /@media \(prefers-reduced-motion: reduce\)/);
});

test("job pages preserve organization-scoped APIs, streaming, and provider-neutral map usage", () => {
  const jobs = read("pages/index.tsx");
  const detail = read("pages/jobs/[jobId].tsx");
  const dispatcher = read("components/map/JobMap.tsx");
  const stream = read("lib/use-job-stream.ts");

  assert.match(jobs, /\/api\/orgs\/\$\{activeOrg\.org\.id\}\/jobs/);
  assert.match(detail, /\/api\/orgs\/\$\{orgId\}\/jobs\/\$\{jobId\}/);
  assert.match(detail, /<JobMap/);
  assert.doesNotMatch(detail, /EsriJobMap/);
  assert.match(dispatcher, /dynamic\(\(\) => import\('\.\/esri\/EsriJobMap'\)/);
  assert.match(stream, /channel: `job:\$\{jobId\}`/);
  assert.match(stream, /return connectionState/);
});
