import { describe, expect, it } from "vitest";
import {
  decodeBase64OutputEnvelope,
  maximumBase64JsonUtf16,
} from "./base64-output";

describe("portable base64 replacement transport", () => {
  it("decodes canonical bounded UTF-8 output", () => {
    expect(
      decodeBase64OutputEnvelope(
        {
          abi: 1,
          ok: true,
          outputBase64: "8J+YgA==",
          outputBytes: 4,
          outputTruncated: false,
        },
        4,
        "Test bridge",
      ),
    ).toEqual({
      abi: 1,
      ok: true,
      output: "😀",
      outputBytes: 4,
      outputTruncated: false,
    });
  });

  it.each(["not base64", "/x==", "8J+YgA="])(
    "rejects non-canonical base64 %j",
    (outputBase64) => {
      expect(() =>
        decodeBase64OutputEnvelope(
          { ok: true, outputBase64, outputBytes: 64 },
          64,
          "Test bridge",
        ),
      ).toThrow(/invalid base64/u);
    },
  );

  it("rejects invalid UTF-8, over-limit output and raw-output fallback", () => {
    expect(() =>
      decodeBase64OutputEnvelope(
        { ok: true, outputBase64: "/w==", outputBytes: 1 },
        1,
        "Test bridge",
      ),
    ).toThrow(/non-UTF-8/u);
    expect(() =>
      decodeBase64OutputEnvelope(
        { ok: true, outputBase64: "YWE=", outputBytes: 1 },
        1,
        "Test bridge",
      ),
    ).toThrow(/output limit/u);
    expect(() =>
      decodeBase64OutputEnvelope(
        { ok: true, output: "raw", outputBase64: "cmF3", outputBytes: 3 },
        3,
        "Test bridge",
      ),
    ).toThrow(/invalid encoded output/u);
  });

  it("rejects encoded output outside a successful replacement envelope", () => {
    expect(() =>
      decodeBase64OutputEnvelope(
        { ok: true, outputBase64: "" },
        undefined,
        "Test bridge",
      ),
    ).toThrow(/match request/u);
    expect(() =>
      decodeBase64OutputEnvelope(
        { ok: false, outputBase64: "" },
        1,
        "Test bridge",
      ),
    ).toThrow(/failure envelope/u);
  });

  it.each([undefined, -1, 1.5, 5])(
    "rejects an invalid declared output byte count %j",
    (outputBytes) => {
      expect(() =>
        decodeBase64OutputEnvelope(
          { ok: true, outputBase64: "", outputBytes },
          4,
          "Test bridge",
        ),
      ).toThrow(/invalid encoded output/u);
    },
  );

  it("bounds decoding by the declared output byte count", () => {
    expect(() =>
      decodeBase64OutputEnvelope(
        { ok: true, outputBase64: "YWE=", outputBytes: 1 },
        64 * 1024 * 1024,
        "Test bridge",
      ),
    ).toThrow(/output limit/u);
  });

  it("computes a predictable base64 JSON envelope bound", () => {
    expect(maximumBase64JsonUtf16(100, 64)).toBe(188);
  });
});
