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

function fixture(
  ruleId: RenderedRuleId,
  variant: RenderedFixture["variant"],
  htmlFile: string,
  options: {
    cell?: Partial<MatrixCell>;
    intentionalContractId?: string;
  } = {},
): RenderedFixture {
  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 renderedFixtureGallery: RenderedFixture[] = [
  fixture("UI-010", "positive", "ui-010-positive.html"),
  fixture("UI-010", "negative", "ui-010-negative.html"),
  fixture("UI-010", "intentional-exception", "ui-010-intentional-exception.html"),
  fixture("UI-010", "rtl", "ui-010-positive.html", {
    cell: { locale: "ar-SA", id: "ui-010-rtl" },
  }),
  fixture("UI-010", "changed-fingerprint", "ui-010-changed-fingerprint.html"),

  fixture("UI-011", "positive", "ui-011-positive.html"),
  fixture("UI-011", "negative", "ui-011-negative.html"),
  fixture("UI-011", "intentional-exception", "ui-011-intentional-exception.html", {
    intentionalContractId: "rendered-ui-011-exception",
  }),

  fixture("UI-012", "positive", "ui-012-positive.html", {
    cell: {
      expectedNetwork: [{ method: "GET", urlPattern: "/api/data", status: 200 }],
    },
  }),
  fixture("UI-012", "negative", "ui-012-negative.html"),
  fixture("UI-012", "intentional-exception", "ui-012-intentional-exception.html", {
    intentionalContractId: "rendered-ui-012-exception",
    cell: {
      expectedNetwork: [{ method: "GET", urlPattern: "/api/allowed", status: 404 }],
    },
  }),

  fixture("UI-013", "positive", "ui-013-positive.html", {
    cell: {
      state: {
        uiI18nCatalog: JSON.stringify(["app.welcome", "app.goodbye"]),
      },
    },
  }),
  fixture("UI-013", "negative", "ui-013-negative.html", {
    cell: {
      state: {
        uiI18nCatalog: JSON.stringify(["app.welcome", "app.goodbye"]),
      },
    },
  }),
  fixture("UI-013", "intentional-exception", "ui-013-intentional-exception.html", {
    cell: {
      state: {
        uiI18nCatalog: JSON.stringify(["app.welcome"]),
        uiLiteralI18nKeys: JSON.stringify(["app.literal.example"]),
      },
    },
  }),

  fixture("UI-014", "positive", "ui-014-positive.html", {
    cell: { locale: "en-US" },
  }),
  fixture("UI-014", "negative", "ui-014-negative.html", {
    cell: { locale: "en-US" },
  }),
  fixture("UI-014", "rtl", "ui-014-rtl-positive.html", {
    cell: { locale: "ar-SA", id: "ui-014-rtl" },
  }),
  fixture("UI-014", "intentional-exception", "ui-014-intentional-exception.html", {
    intentionalContractId: "rendered-ui-014-exception",
    cell: { locale: "en-US" },
  }),

  fixture("UI-015", "positive", "ui-015-positive.html", {
    cell: {
      state: {
        uiRequiredLandmark: "main",
        uiRequiredLandmarkConfirmed: "true",
      },
    },
  }),
  fixture("UI-015", "negative", "ui-015-negative.html", {
    cell: {
      state: {
        uiRequiredLandmark: "main",
        uiRequiredLandmarkConfirmed: "true",
      },
    },
  }),
  fixture("UI-015", "intentional-exception", "ui-015-intentional-exception.html", {
    intentionalContractId: "rendered-ui-015-exception",
    cell: {
      state: {
        uiRequiredLandmark: "main",
        uiRequiredLandmarkConfirmed: "true",
      },
    },
  }),

  fixture("UI-016", "positive", "ui-016-positive.html", {
    cell: {
      id: "ui-016-positive",
      state: { uiCompletionSignal: "#ready" },
    },
  }),
  fixture("UI-016", "negative", "ui-016-negative.html", {
    cell: {
      id: "ui-016-negative",
      state: { uiCompletionSignal: "#ready" },
    },
  }),
  fixture("UI-016", "intentional-exception", "ui-016-intentional-exception.html", {
    intentionalContractId: "rendered-ui-016-exception",
    cell: { state: { uiCompletionSignal: "#ready" } },
  }),

  fixture("UI-017", "positive", "ui-017-positive.html"),
  fixture("UI-017", "negative", "ui-017-negative.html"),
  fixture("UI-017", "intentional-exception", "ui-017-intentional-exception.html", {
    cell: { state: { uiDocumentOverflowIntentional: "true" } },
  }),
  fixture("UI-017", "rtl", "ui-017-positive.html", {
    cell: { locale: "ar-SA", id: "ui-017-rtl" },
  }),

  fixture("UI-018", "positive", "ui-018-positive.html", {
    cell: { state: { uiHydrationAdapter: "react" } },
  }),
  fixture("UI-018", "negative", "ui-018-negative.html", {
    cell: { state: { uiHydrationAdapter: "react" } },
  }),
  fixture("UI-018", "intentional-exception", "ui-018-intentional-exception.html", {
    intentionalContractId: "rendered-ui-018-exception",
    cell: { state: { uiHydrationAdapter: "react" } },
  }),
];

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

export function fixturesForRule(ruleId: RenderedRuleId): RenderedFixture[] {
  return renderedFixtureGallery.filter((entry) => entry.ruleId === ruleId);
}

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