import { describe, it, expect } from "vitest";
import { seedOnderdelen } from "./onderdelen";
import { seedModellen } from "./modellen";
import { assertSeedBibliotheek, valideerSeedBibliotheek } from "./schema-guard";
import type { Modeldocument, Modelonderdeel } from "./types";

// ── Schema-guard ─────────────────────────────────────────────────────────────
// De guard zelf draait als laadcontrole in data/modeldocumenten/index.ts
// (dev/test/build falen meteen op ongeldige seed-data); deze test bewaakt
// (1) dat de echte bibliotheek geldig blijft — met de volledige probleemlijst
// als foutmelding — en (2) dat elke probleemklasse effectief gedetecteerd
// wordt (anders beschermt de guard tegen niets).

function onderdeel(overschrijf: Partial<Modelonderdeel> = {}): Modelonderdeel {
  return {
    id: "o1",
    titel: "Testonderdeel",
    categorie: "goed",
    omschrijving: "x",
    tekst: "Tekst.",
    varianten: [],
    parameters: [],
    toepasbaarOp: [],
    versie: "1.0",
    datum: "2026-01-01",
    ...overschrijf,
  };
}

function model(overschrijf: Partial<Modeldocument> = {}): Modeldocument {
  return {
    id: "m1",
    titel: "Testmodel",
    akteType: "test",
    omschrijving: "x",
    structuur: [{ onderdeelId: "o1", verplicht: true }],
    versie: "1.0",
    datum: "2026-01-01",
    ...overschrijf,
  };
}

describe("schema-guard — seed-bibliotheek", () => {
  it("de volledige seed-bibliotheek is geldig", () => {
    expect(valideerSeedBibliotheek(seedOnderdelen, seedModellen)).toEqual([]);
  });
});

describe("schema-guard — detectie per probleemklasse", () => {
  it("leeg verplicht veld op een onderdeel", () => {
    const p = valideerSeedBibliotheek([onderdeel({ titel: "  " })], []);
    expect(p.join()).toContain('"titel" is leeg');
  });

  it("dubbel onderdeel-id", () => {
    const p = valideerSeedBibliotheek([onderdeel(), onderdeel()], []);
    expect(p.join()).toContain('dubbel onderdeel-id "o1"');
  });

  it("onderdeel zonder inhoud (geen tekst, geen varianten)", () => {
    const p = valideerSeedBibliotheek([onderdeel({ tekst: "" })], []);
    expect(p.join()).toContain("geen basistekst én geen varianten");
  });

  it("dubbel of leeg variant-id en lege hypothese/tekst", () => {
    const p = valideerSeedBibliotheek(
      [
        onderdeel({
          varianten: [
            { id: "a", hypothese: "h", tekst: "t" },
            { id: "a", hypothese: "", tekst: "" },
            { id: "", hypothese: "h", tekst: "t" },
          ],
        }),
      ],
      []
    );
    expect(p.join()).toContain('dubbel variant-id "a"');
    expect(p.join()).toContain('"hypothese" is leeg');
    expect(p.join()).toContain('"tekst" is leeg');
    expect(p.join()).toContain("variant zonder id");
  });

  it("hangende of zelfverwijzende vertalingVanId (onderdeel én model)", () => {
    const p = valideerSeedBibliotheek(
      [onderdeel({ vertalingVanId: "bestaat-niet" }), onderdeel({ id: "o2", vertalingVanId: "o2" })],
      [model({ vertalingVanId: "bestaat-niet" })]
    );
    expect(p.join()).toContain('onderdeel "o1": vertalingVanId "bestaat-niet" bestaat niet');
    expect(p.join()).toContain('onderdeel "o2": vertalingVanId verwijst naar zichzelf');
    expect(p.join()).toContain('model "m1": vertalingVanId "bestaat-niet" bestaat niet');
  });

  it("lege wetsbasis-vermelding", () => {
    const p = valideerSeedBibliotheek([onderdeel({ wetsbasis: ["art. 1 BW", " "] })], []);
    expect(p.join()).toContain('"wetsbasis" bevat een lege vermelding');
  });

  it("dubbel model-id en lege structuur", () => {
    const p = valideerSeedBibliotheek([onderdeel()], [model(), model({ structuur: [] })]);
    expect(p.join()).toContain('dubbel model-id "m1"');
    expect(p.join()).toContain("lege structuur");
  });

  it("structuurverwijzing naar een onbestaand onderdeel", () => {
    const p = valideerSeedBibliotheek([onderdeel()], [model({ structuur: [{ onderdeelId: "spook", verplicht: true }] })]);
    expect(p.join()).toContain('onbestaand onderdeel "spook"');
  });

  it("geldige minimale bibliotheek geeft geen problemen", () => {
    expect(valideerSeedBibliotheek([onderdeel()], [model()])).toEqual([]);
  });

  it("assertSeedBibliotheek (de laadcontrole) gooit één fout met alle problemen", () => {
    expect(() => assertSeedBibliotheek([onderdeel({ titel: "" }), onderdeel()], [])).toThrow(
      /Seed-bibliotheek ongeldig \(2 /
    );
    expect(() => assertSeedBibliotheek([onderdeel()], [model()])).not.toThrow();
  });
});
