import { describe, expect, test } from "bun:test";
import { ContractRegistry, checkContractCompatibility, defineEvent, v } from "../src/index.ts";

describe("boundary contract registry", () => {
  test("registers typed, deterministic multi-boundary snapshots", () => {
    const registry = new ContractRegistry()
      .register(
        defineEvent({
          name: "user.created",
          version: 1,
          payload: v.object({ id: v.string().uuid() }),
        }),
      )
      .register({
        kind: "queue",
        name: "email.send",
        version: 1,
        payload: v.object({ to: v.string().email() }),
      });
    expect(registry.snapshot().contracts.map((item) => `${item.kind}:${item.name}`)).toEqual([
      "pubsub:user.created",
      "queue:email.send",
    ]);
  });

  test("rejects duplicate identities", () => {
    const registry = new ContractRegistry();
    const contract = {
      kind: "api",
      name: "users",
      version: 1,
      payload: v.object({ id: v.string() }),
    } as const;
    registry.register(contract);
    expect(() => registry.register(contract)).toThrow("Duplicate contract");
  });

  test("reports breaking fields, types, requirements, rules, and consumers", () => {
    const previous = new ContractRegistry()
      .register({
        kind: "webhook",
        name: "invoice.paid",
        version: 1,
        consumers: ["accounting", "email"],
        payload: v.object({
          email: v.string().optional(),
          count: v.number().min(0),
          legacy: v.string(),
        }),
      })
      .snapshot();
    const current = new ContractRegistry()
      .register({
        kind: "webhook",
        name: "invoice.paid",
        version: 1,
        payload: v.object({ email: v.string(), count: v.string().min(2), added: v.string() }),
      })
      .snapshot();
    const issues = checkContractCompatibility(previous, current);
    expect(issues.map((issue) => issue.code)).toEqual([
      "WRN-CONTRACT-FIELD-REQUIRED",
      "WRN-CONTRACT-FIELD-TYPE",
      "WRN-CONTRACT-RULE-TIGHTENED",
      "WRN-CONTRACT-FIELD-REMOVED",
      "WRN-CONTRACT-FIELD-REQUIRED",
    ]);
    expect(issues.every((issue) => issue.consumers.includes("accounting"))).toBe(true);
  });
});
