import { describe, expect, it } from "vitest";
import type { RegexExecutionRequest } from "../../../model/match";
import {
  JAVA_BRIDGE_ABI_VERSION,
  JAVA_ENGINE_IDENTITY,
} from "../java/JavaEngineAdapter";
import type { TeaVmJavaRegexModule } from "../java/java-module";
import {
  ScalaEngineAdapter,
  SCALA_FLAVOUR_VERSION,
} from "./ScalaEngineAdapter";

function fields(...values: readonly (string | number | boolean)[]): string {
  return values
    .map((value) => {
      const encoded =
        typeof value === "boolean" ? (value ? "1" : "0") : String(value);
      return `${encoded.length}:${encoded}`;
    })
    .join("");
}

function module(): TeaVmJavaRegexModule {
  return {
    bridgeAbiVersion: () => JAVA_BRIDGE_ABI_VERSION,
    engineIdentity: () => JAVA_ENGINE_IDENTITY,
    selfTest: () => 0,
    execute: () => fields("1", "ok", 0, false, 1, 0, 1),
    replace: () => fields("1", "ok", 0, false, 1, 0, 1, false, "x"),
  };
}

function request(): RegexExecutionRequest {
  return {
    flavour: "scala",
    flavourVersion: SCALA_FLAVOUR_VERSION,
    pattern: "a",
    flags: ["g"],
    options: {},
    subject: "a",
    captureMetadata: [],
    scanAll: true,
    maximumMatches: 10,
    maximumCaptureRows: 100,
  };
}

describe("Scala/JVM compatibility adapter", () => {
  it("executes through the disclosed TeaVM Java backend", async () => {
    const adapter = new ScalaEngineAdapter(module(), "unit-test runtime");
    const result = await adapter.execute(request());

    expect(result.accepted).toBe(true);
    expect(result.engine).toEqual(
      expect.objectContaining({
        flavour: "scala",
        engineName: "Scala/JVM regex via TeaVM java.util.regex",
        runtimeVersion: expect.stringContaining("no Scala runtime"),
      }),
    );
    expect(result.matches[0]).toMatchObject({
      value: "a",
      range: { startUtf16: 0, endUtf16: 1 },
    });
  });

  it("rejects an undisclosed profile version", async () => {
    const adapter = new ScalaEngineAdapter(module());
    await expect(
      adapter.execute({ ...request(), flavourVersion: "Scala.js" }),
    ).rejects.toThrow("unsupported");
  });
});
