import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { MATRIX_CELL_VERSION } from "../../../schema/src/records/context.js";
import type { MatrixCell } from "../../../schema/src/records/context.js";
import type { AssetsFixture, AssetsRuleId } from "../../src/assets/types.js";

const FIXTURES_DIR = join(dirname(fileURLToPath(import.meta.url)), "html");

function readHtml(name: string): string {
  return readFileSync(join(FIXTURES_DIR, name), "utf8");
}

function baseCell(overrides: Partial<MatrixCell> = {}): MatrixCell {
  return {
    schemaVersion: MATRIX_CELL_VERSION,
    id: "assets-cell-fixture",
    creationSource: {
      runId: "assets-fixture-run",
      component: "orchestrator",
      componentId: "assets-fixtures",
    },
    routeId: "assets-fixture",
    url: "/fixture",
    role: "anonymous",
    locale: "en-US",
    viewport: { width: 800, height: 600, deviceScaleFactor: 1 },
    state: { uiCompletionSignal: "#ready" },
    actions: [],
    seed: "",
    ...overrides,
  };
}

function settledCell(overrides: Partial<MatrixCell> = {}): Partial<MatrixCell> {
  return {
    state: { uiCompletionSignal: "#ready", ...(overrides.state ?? {}) },
    ...overrides,
  };
}

function fixture(
  ruleId: AssetsRuleId,
  variant: AssetsFixture["variant"],
  htmlFile: string,
  options: {
    cell?: Partial<MatrixCell>;
    intentionalContractId?: string;
  } = {},
): AssetsFixture {
  return {
    fixtureId: `${ruleId.toLowerCase()}-${variant}`,
    ruleId,
    variant,
    route: "/fixture",
    html: readHtml(htmlFile),
    ...(options.cell === undefined ? {} : { cell: options.cell }),
    ...(options.intentionalContractId === undefined
      ? {}
      : { intentionalContractId: options.intentionalContractId }),
  };
}

export const assetsFixtureGallery: AssetsFixture[] = [
  fixture("UI-070", "positive", "ui-070-positive.html", { cell: settledCell() }),
  fixture("UI-070", "negative", "ui-070-negative.html", { cell: settledCell() }),
  fixture("UI-070", "intentional-exception", "ui-070-intentional-exception.html", {
    cell: settledCell(),
    intentionalContractId: "assets-ui-070-exception",
  }),
  fixture("UI-070", "rtl", "ui-070-rtl-positive.html", {
    cell: settledCell({ locale: "ar-SA", id: "ui-070-rtl" }),
  }),
  fixture("UI-070", "changed-fingerprint", "ui-070-changed-fingerprint.html", {
    cell: settledCell({ id: "ui-070-changed-fingerprint" }),
  }),

  fixture("UI-071", "positive", "ui-071-positive.html", { cell: settledCell() }),
  fixture("UI-071", "negative", "ui-071-negative.html", { cell: settledCell() }),
  fixture("UI-071", "intentional-exception", "ui-071-intentional-exception.html", {
    cell: settledCell(),
    intentionalContractId: "assets-ui-071-exception",
  }),
  fixture("UI-071", "rtl", "ui-071-rtl-positive.html", {
    cell: settledCell({ locale: "ar-SA", id: "ui-071-rtl" }),
  }),
  fixture("UI-071", "changed-fingerprint", "ui-071-changed-fingerprint.html", {
    cell: settledCell({ id: "ui-071-changed-fingerprint" }),
  }),

  fixture("UI-072", "positive", "ui-072-positive.html", { cell: settledCell() }),
  fixture("UI-072", "negative", "ui-072-negative.html", { cell: settledCell() }),
  fixture("UI-072", "intentional-exception", "ui-072-intentional-exception.html", {
    cell: settledCell(),
    intentionalContractId: "assets-ui-072-exception",
  }),
  fixture("UI-072", "rtl", "ui-072-rtl-positive.html", {
    cell: settledCell({ locale: "ar-SA", id: "ui-072-rtl" }),
  }),
  fixture("UI-072", "changed-fingerprint", "ui-072-changed-fingerprint.html", {
    cell: settledCell({ id: "ui-072-changed-fingerprint" }),
  }),
];

export function cellForFixture(entry: AssetsFixture): MatrixCell {
  return baseCell({
    id: entry.fixtureId,
    routeId: entry.fixtureId,
    url: entry.route,
    ...(entry.cell ?? {}),
  });
}

export function routesForFixture(fixture: AssetsFixture): Record<
  string,
  string | { status: number; body: string }
> {
  return {
    "/fixture": fixture.html,
    "/missing-image.png": { status: 404, body: "not found" },
  };
}

export function fixturesForRule(ruleId: AssetsRuleId): AssetsFixture[] {
  return assetsFixtureGallery.filter((entry) => entry.ruleId === ruleId);
}

export function positiveFixture(ruleId: AssetsRuleId): AssetsFixture {
  const match = fixturesForRule(ruleId).find((entry) => entry.variant === "positive");
  if (match === undefined) {
    throw new Error(`positive fixture missing for ${ruleId}`);
  }
  return match;
}

export function negativeFixture(ruleId: AssetsRuleId): AssetsFixture {
  const match = fixturesForRule(ruleId).find((entry) => entry.variant === "negative");
  if (match === undefined) {
    throw new Error(`negative fixture missing for ${ruleId}`);
  }
  return match;
}
