import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
import fixtures from "../../../baseline/schemas/v2/route-response-fixtures.json" assert { type: "json" };
import {
  assertV2ResponseCompatible,
  compatibilityViolations,
  type ExactV2Fixture,
  type V2RouteFixture,
} from "../../compat/v2-response-compat";

const routes = readFileSync(resolve(import.meta.dirname, "../../../baseline/extracted/v2_api_routes.txt"), "utf8")
  .split("\n")
  .map((line) => line.trim())
  .filter(Boolean);
const routeFixtures = fixtures.fixtures as V2RouteFixture[];
const exact = routeFixtures.filter((fixture): fixture is ExactV2Fixture => fixture.fixtureStatus === "exact");

describe("V2 response compatibility fixture baseline", () => {
  it("covers every inventoried V2 route exactly once", () => {
    expect(fixtures.inventory.routeCount).toBe(routes.length);
    expect(routeFixtures.map((fixture) => fixture.path)).toEqual(routes);
    expect(new Set(routeFixtures.map((fixture) => fixture.path)).size).toBe(routes.length);
  });

  it("uses schemas only for route-specific recorded evidence", () => {
    expect(exact).toHaveLength(1);
    for (const fixture of exact) {
      expect(fixture.evidence.capturedPath).toBe(fixture.path);
      expect(fixture.responseSchema.required?.length).toBeGreaterThan(0);
    }
    for (const fixture of routeFixtures.filter((fixture) => fixture.fixtureStatus === "unresolved")) {
      expect(fixture.responseSchema).toBeNull();
      expect(fixture.method).toBeNull();
    }
    expect(fixtures.unmatchedEvidence).toHaveLength(2);
  });

  it("preserves every captured field and permits additive optional fields", () => {
    const contracts = exact.find((fixture) => fixture.path === "/api/contracts")!;
    const snapshot = JSON.parse(readFileSync(resolve(import.meta.dirname, "../../../baseline/raw_api_contracts.txt"), "utf8"));
    expect(() => assertV2ResponseCompatible(contracts.responseSchema, snapshot)).not.toThrow();

    const additive = { ...snapshot, protocolVersion: "v2", dataSourceErrors: [] };
    expect(() => assertV2ResponseCompatible(contracts.responseSchema, additive)).not.toThrow();

    const removed = { ...snapshot } as Record<string, unknown>;
    delete removed.totalContracts;
    expect(compatibilityViolations(contracts.responseSchema, removed)).toContain("$.totalContracts: missing captured field");

    const repurposed = { ...snapshot, totalContracts: String(snapshot.totalContracts) };
    expect(compatibilityViolations(contracts.responseSchema, repurposed)).toContain("$.totalContracts: expected integer, received string");
  });
});
