import { describe, it, expect } from "vitest";
// ── Dekking-guard: élke MCP-tool is ontdekbaar via haalWerkwijze ──────────────
// De werkwijze (data/werkwijze.ts) is het zelf-ontdekkingspunt van de
// MCP-server: een agent die enkel haalWerkwijze leest, moet gegarandeerd álle
// operationele mogelijkheden kunnen vinden. Deze test bewaakt dat in beide
// richtingen: (1) elke operationId uit de OpenAPI-spec — en dus elke
// MCP-tool — komt in minstens één werkwijze-stap voor (een nieuwe endpoint
// zonder plaats in het stappenplan faalt hier, nooit stilzwijgend
// onvindbaar); (2) elke tool-verwijzing in de werkwijze bestaat echt (geen
// typo's of verwijzingen naar geschrapte tools).

import { bouwOpenApiSpec } from "@/lib/openapi";
import { lijstMcpTools } from "@/lib/mcp/server";
import { WERKWIJZE } from "@/data/werkwijze";

function alleOperationIds(): string[] {
  const ids: string[] = [];
  for (const padItem of Object.values(bouwOpenApiSpec().paths)) {
    if (padItem.get) ids.push(padItem.get.operationId);
    if (padItem.post) ids.push(padItem.post.operationId);
  }
  return ids;
}

const werkwijzeTools = new Set(WERKWIJZE.stappen.flatMap((s) => s.tools));

describe("MCP-dekking van de werkwijze (zelf-ontdekkend stappenplan)", () => {
  it("elke operationId uit de OpenAPI-spec staat in minstens één werkwijze-stap", () => {
    const ontbrekend = alleOperationIds().filter((id) => !werkwijzeTools.has(id));
    expect(
      ontbrekend,
      `Nieuwe endpoint(s) zonder plaats in het stappenplan (data/werkwijze.ts): ${ontbrekend.join(", ")} — voeg ze toe aan de passende stap zodat een agent ze via haalWerkwijze kan ontdekken.`
    ).toEqual([]);
  });

  it("elke tool-verwijzing in de werkwijze bestaat echt in de spec (geen typo's)", () => {
    const bekend = new Set(alleOperationIds());
    const onbekend = [...werkwijzeTools].filter((t) => !bekend.has(t));
    expect(onbekend, `Werkwijze verwijst naar onbestaande tool(s): ${onbekend.join(", ")}`).toEqual([]);
  });

  it("de MCP-toolcatalogus is exact de spec: zelfde namen, allemaal met omschrijving", () => {
    const tools = lijstMcpTools();
    expect(tools.map((t) => t.name).sort()).toEqual(alleOperationIds().sort());
    for (const tool of tools) {
      expect(tool.description, `tool ${tool.name} mist een omschrijving`).toBeTruthy();
    }
  });

  it("de stappen zijn doorlopend genummerd (geen gaten na een hernummering)", () => {
    expect(WERKWIJZE.stappen.map((s) => s.stap)).toEqual(WERKWIJZE.stappen.map((_, i) => i));
  });
});
