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 { A11yFixture, A11yRuleId } from "../../src/a11y/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: "a11y-cell-fixture",
    creationSource: {
      runId: "a11y-fixture-run",
      component: "orchestrator",
      componentId: "a11y-fixtures",
    },
    routeId: "a11y-fixture",
    url: "/fixture",
    role: "anonymous",
    locale: "en-US",
    viewport: { width: 800, height: 600, deviceScaleFactor: 1 },
    state: {},
    actions: [],
    seed: "",
    ...overrides,
  };
}

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

function clickAction(id: string, target: string, settleMs = "50"): MatrixCell["actions"][number] {
  return {
    id,
    kind: "click",
    target,
    params: { settleMs },
  };
}

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

function cellForRule(ruleId: A11yRuleId, overrides?: Partial<MatrixCell>): Partial<MatrixCell> {
  if (ruleId === "UI-062") {
    return settledCell({
      actions: [clickAction("advance", "#ready")],
      ...overrides,
    });
  }
  return settledCell(overrides);
}

export const a11yFixtureGallery: A11yFixture[] = [
  fixture("UI-060", "positive", "ui-060-positive.html", { cell: cellForRule("UI-060") }),
  fixture("UI-060", "negative", "ui-060-negative.html", { cell: cellForRule("UI-060") }),
  fixture("UI-060", "intentional-exception", "ui-060-intentional-exception.html", {
    cell: cellForRule("UI-060"),
    intentionalContractId: "a11y-ui-060-exception",
  }),
  fixture("UI-060", "rtl", "ui-060-rtl-positive.html", {
    cell: cellForRule("UI-060", { locale: "ar-SA", id: "ui-060-rtl" }),
  }),
  fixture("UI-060", "changed-fingerprint", "ui-060-changed-fingerprint.html", {
    cell: cellForRule("UI-060", { id: "ui-060-changed-fingerprint" }),
  }),

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

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

  fixture("UI-082", "positive", "ui-082-positive.html", {
    cell: cellForRule("UI-082", { state: { a11yDisabledAxeRules: "duplicate-id" } }),
  }),
  fixture("UI-082", "negative", "ui-082-negative.html", { cell: cellForRule("UI-082") }),
  fixture("UI-082", "intentional-exception", "ui-082-intentional-exception.html", {
    cell: cellForRule("UI-082", {
      state: { a11yDisabledAxeRules: "duplicate-id" },
    }),
    intentionalContractId: "a11y-ui-082-exception",
  }),
  fixture("UI-082", "rtl", "ui-082-rtl-positive.html", {
    cell: cellForRule("UI-082", {
      locale: "ar-SA",
      id: "ui-082-rtl",
      state: { a11yDisabledAxeRules: "duplicate-id" },
    }),
  }),
  fixture("UI-082", "changed-fingerprint", "ui-082-changed-fingerprint.html", {
    cell: cellForRule("UI-082", {
      id: "ui-082-changed-fingerprint",
      state: { a11yDisabledAxeRules: "duplicate-id" },
    }),
  }),
];

export const forcedColorsPositiveFixture: A11yFixture = {
  fixtureId: "ui-a11-forced-colors-positive",
  ruleId: "UI-060",
  variant: "positive",
  route: "/fixture",
  html: readHtml("ui-a11-forced-colors-positive.html"),
  cell: settledCell({
    id: "ui-a11-forced-colors-positive",
    routeId: "ui-a11-forced-colors-positive",
    state: {
      uiCompletionSignal: "#ready",
      a11yMediaMode: "forced-colors:active",
    },
  }),
};

export const forcedColorsUnsupportedFixture: A11yFixture = {
  fixtureId: "ui-a11-forced-colors-unsupported",
  ruleId: "UI-082",
  variant: "positive",
  route: "/fixture",
  html: readHtml("ui-a11-forced-colors-unsupported.html"),
  cell: settledCell({
    id: "ui-a11-forced-colors-unsupported",
    routeId: "ui-a11-forced-colors-unsupported",
    state: {
      uiCompletionSignal: "#ready",
      a11yMediaMode: "forced-colors:active",
    },
  }),
};

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

export function fixturesForRule(ruleId: A11yRuleId): A11yFixture[] {
  return a11yFixtureGallery.filter((entry) => entry.ruleId === ruleId);
}

export function positiveFixture(ruleId: A11yRuleId): A11yFixture {
  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: A11yRuleId): A11yFixture {
  const match = fixturesForRule(ruleId).find((entry) => entry.variant === "negative");
  if (match === undefined) {
    throw new Error(`negative fixture missing for ${ruleId}`);
  }
  return match;
}

export function routesForFixture(fixture: A11yFixture): Record<string, string> {
  return { "/fixture": fixture.html };
}
