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 { InteractionFixture, InteractionRuleId } from "../../src/interaction/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: "interaction-cell-fixture",
    creationSource: {
      runId: "interaction-fixture-run",
      component: "orchestrator",
      componentId: "interaction-fixtures",
    },
    routeId: "interaction-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 {
    state: { uiCompletionSignal: "#ready" },
    ...overrides,
  };
}

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

function fillAction(id: string, target: string, value: string): MatrixCell["actions"][number] {
  return {
    id,
    kind: "fill",
    target,
    params: { value, settleMs: "50" },
  };
}

function fixture(
  ruleId: InteractionRuleId,
  variant: InteractionFixture["variant"],
  htmlFile: string,
  options: {
    cell?: Partial<MatrixCell>;
    intentionalContractId?: string;
  } = {},
): InteractionFixture {
  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 actionsForRule(ruleId: InteractionRuleId): MatrixCell["actions"] {
  switch (ruleId) {
    case "UI-033":
      return [clickAction("save", "#save")];
    case "UI-035":
      return [
        fillAction("fill-email", "#email", "user@example.com"),
        fillAction("fill-password", "#password", "secret-token"),
        clickAction("submit", "#submit"),
      ];
    case "UI-036":
      return [clickAction("cancel", "#cancel")];
    case "UI-037":
      return [clickAction("reorder", "#reorder")];
    case "UI-038":
      return [];
    default:
      return [];
  }
}

function cellActionsForRule(ruleId: InteractionRuleId, overrides?: Partial<MatrixCell>): Partial<MatrixCell> {
  const actions = overrides?.actions ?? actionsForRule(ruleId);
  return {
    actions,
    ...settledCell(overrides),
  };
}

export const interactionFixtureGallery: InteractionFixture[] = [
  fixture("UI-033", "positive", "ui-033-positive.html", {
    cell: cellActionsForRule("UI-033"),
  }),
  fixture("UI-033", "negative", "ui-033-negative.html", {
    cell: cellActionsForRule("UI-033"),
  }),
  fixture("UI-033", "intentional-exception", "ui-033-intentional-exception.html", {
    cell: cellActionsForRule("UI-033"),
    intentionalContractId: "interaction-ui-033-exception",
  }),
  fixture("UI-033", "rtl", "ui-033-rtl-positive.html", {
    cell: cellActionsForRule("UI-033", { locale: "ar-SA", id: "ui-033-rtl" }),
  }),
  fixture("UI-033", "changed-fingerprint", "ui-033-changed-fingerprint.html", {
    cell: cellActionsForRule("UI-033", { id: "ui-033-changed-fingerprint" }),
  }),

  fixture("UI-035", "positive", "ui-035-positive.html", {
    cell: cellActionsForRule("UI-035"),
  }),
  fixture("UI-035", "negative", "ui-035-negative.html", {
    cell: cellActionsForRule("UI-035"),
  }),
  fixture("UI-035", "intentional-exception", "ui-035-intentional-exception.html", {
    cell: cellActionsForRule("UI-035", {
      actions: [
        fillAction("fill-email", "#email", "user@example.com"),
        clickAction("submit", "#submit"),
      ],
    }),
    intentionalContractId: "interaction-ui-035-exception",
  }),
  fixture("UI-035", "rtl", "ui-035-rtl-positive.html", {
    cell: cellActionsForRule("UI-035", { locale: "ar-SA", id: "ui-035-rtl" }),
  }),
  fixture("UI-035", "changed-fingerprint", "ui-035-changed-fingerprint.html", {
    cell: cellActionsForRule("UI-035", {
      id: "ui-035-changed-fingerprint",
      actions: [
        fillAction("fill-email", "#email", "user@example.com"),
        clickAction("submit", "#submit"),
      ],
    }),
  }),

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

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

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

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

export function fixturesForRule(ruleId: InteractionRuleId): InteractionFixture[] {
  return interactionFixtureGallery.filter((entry) => entry.ruleId === ruleId);
}

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