import {
  PORTABLE_BRIDGE_ABI_VERSION,
  PortableEngineAdapter,
  type PortableEngineConfiguration,
  type PortableRegexBridge,
} from "../portable/PortableEngineAdapter";

export const RUST_FLAVOUR_VERSION = "Rust regex 1.13.1 WebAssembly";
export const RUST_ENGINE_VERSION = "1.13.1";
export const RUST_RUNTIME_VERSION = "rustc 1.97.1 wasm32-unknown-unknown";

function isRecord(value: unknown): value is Readonly<Record<string, unknown>> {
  return typeof value === "object" && value !== null && !Array.isArray(value);
}

function configuration(runtimeIdentity?: string): PortableEngineConfiguration {
  return {
    flavour: "rust",
    flavourLabel: "Rust regex",
    expectedFlavourVersion: RUST_FLAVOUR_VERSION,
    engineName: "Rust regex crate",
    engineVersion: RUST_ENGINE_VERSION,
    runtimeVersion: [RUST_RUNTIME_VERSION, runtimeIdentity]
      .filter(Boolean)
      .join(" · "),
    offsetUnit: "utf8-byte",
    supportedFlags: "gimsUuxR",
    rejectLoneSurrogates: true,
    capabilities: {
      compilation: true,
      matching: true,
      replacement: true,
      namedCaptures: true,
      captureHistory: false,
      actualTrace: false,
      benchmark: false,
    },
    validateIdentity: (envelope) => {
      const identity = envelope.identity;
      if (
        envelope.abi !== PORTABLE_BRIDGE_ABI_VERSION ||
        envelope.ok !== true ||
        !isRecord(identity) ||
        identity.bridge !== "regex-tools-rust-json" ||
        identity.bridgeVersion !== PORTABLE_BRIDGE_ABI_VERSION ||
        identity.engine !== "Rust regex crate" ||
        identity.engineVersion !== RUST_ENGINE_VERSION ||
        identity.offsetUnit !== "utf8-byte" ||
        identity.rustcVersion !== "rustc 1.97.1 (8bab26f4f 2026-07-14)" ||
        identity.selfTest !== true
      ) {
        throw new Error(
          "The bundled Rust regex runtime failed its identity self-test.",
        );
      }
    },
  };
}

export class RustEngineAdapter extends PortableEngineAdapter {
  constructor(bridge: PortableRegexBridge, runtimeIdentity?: string) {
    super(bridge, configuration(runtimeIdentity));
  }
}
