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

export const PHP_FLAVOUR_VERSION = "PHP 8.5.8 preg / PCRE2 10.44";
export const PHP_ENGINE_VERSION = "PHP 8.5.8 preg / PCRE2 10.44";
export const PHP_WASM_PACKAGE_VERSION = "3.1.46";

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: "php",
    flavourLabel: "PHP preg",
    expectedFlavourVersion: PHP_FLAVOUR_VERSION,
    engineName: "PHP preg (PCRE2)",
    engineVersion: PHP_ENGINE_VERSION,
    runtimeVersion: [
      `@php-wasm/web-8-5 ${PHP_WASM_PACKAGE_VERSION}`,
      "Asyncify",
      "wasm32-emscripten",
      runtimeIdentity,
    ]
      .filter(Boolean)
      .join(" · "),
    offsetUnit: "utf8-byte",
    supportedFlags: "gimsxuUADJnr",
    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-php-json" ||
        identity.bridgeVersion !== PORTABLE_BRIDGE_ABI_VERSION ||
        identity.phpVersion !== "8.5.8" ||
        identity.phpSapi !== "wasm" ||
        identity.pcreVersion !== "10.44" ||
        typeof identity.pcreVersionFull !== "string" ||
        !identity.pcreVersionFull.startsWith("10.44 ") ||
        identity.integerBytes !== 8 ||
        identity.offsetUnit !== "utf8-byte" ||
        identity.selfTest !== true
      ) {
        throw new Error(
          "The bundled PHP preg runtime failed its identity self-test.",
        );
      }
    },
  };
}

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