import { afterEach, describe, expect, test } from "bun:test";
import { mkdir, rm, writeFile } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { runContractsCommand } from "../src/contracts-command.ts";

const roots: string[] = [];
afterEach(async () =>
  Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true }))),
);

async function fixture(): Promise<string> {
  const root = join(tmpdir(), `wrnexus-contracts-${crypto.randomUUID()}`);
  roots.push(root);
  await mkdir(root, { recursive: true });
  await writeFile(
    join(root, "wrnexus.contracts.json"),
    JSON.stringify({
      format: 1,
      contracts: [
        {
          kind: "queue",
          name: "mail",
          version: 1,
          consumers: ["worker"],
          payload: {
            type: "object",
            fields: { to: { type: "string", rules: [] } },
          },
        },
      ],
    }),
  );
  return root;
}

describe("contracts command", () => {
  test("snapshots and checks compatible contracts", async () => {
    const root = await fixture();
    expect((await runContractsCommand(root, "snapshot")).ok).toBe(true);
    expect((await runContractsCommand(root, "check")).ok).toBe(true);
  });

  test("returns a failed result for breaking changes", async () => {
    const root = await fixture();
    await runContractsCommand(root, "snapshot");
    await writeFile(
      join(root, "wrnexus.contracts.json"),
      JSON.stringify({ format: 1, contracts: [] }),
    );
    const result = await runContractsCommand(root, "check");
    expect(result).toMatchObject({ ok: false, issueCount: 1 });
  });

  test("requires an explicit baseline", async () => {
    const root = await fixture();
    await expect(runContractsCommand(root, "check")).rejects.toThrow("WRN-CONTRACT-BASELINE");
  });
});
