import { describe, it, expect } from "vitest";
import { verwerkBericht } from "./protocol";

// Deze tests raken enkel de protocolpaden die vóór de REST-fetch afhandelen
// (initialize, tools/list, en de foutpaden van tools/call): geen netwerk nodig.
const ORIGIN = "http://localhost";

describe("verwerkBericht — protocol", () => {
  it("initialize spiegelt een ondersteunde protocolversie en meldt de tools-capability", async () => {
    const antwoord = await verwerkBericht(
      { jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2025-03-26" } },
      ORIGIN,
    );
    const result = antwoord?.result as { protocolVersion: string; capabilities: { tools: unknown } };
    expect(result.protocolVersion).toBe("2025-03-26");
    expect(result.capabilities.tools).toBeDefined();
  });

  it("initialize valt terug op de standaardversie bij een onbekende protocolversie", async () => {
    const antwoord = await verwerkBericht(
      { jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "1999-01-01" } },
      ORIGIN,
    );
    const result = antwoord?.result as { protocolVersion: string };
    expect(result.protocolVersion).toBe("2025-06-18");
  });

  it("tools/list levert getitelde tools met input- en (waar van toepassing) outputSchema", async () => {
    const antwoord = await verwerkBericht({ jsonrpc: "2.0", id: 2, method: "tools/list" }, ORIGIN);
    const { tools } = antwoord?.result as {
      tools: { name: string; inputSchema: unknown; outputSchema?: unknown }[];
    };
    expect(tools.length).toBeGreaterThan(0);
    for (const tool of tools) expect(tool.inputSchema).toBeDefined();
    // Minstens één tool (de Word-generatie) belooft een gestructureerd resultaat.
    expect(tools.some((t) => t.outputSchema !== undefined)).toBe(true);
  });

  it("tools/call met een onbekende tool geeft een -32602-protocolfout met hint", async () => {
    const antwoord = await verwerkBericht(
      { jsonrpc: "2.0", id: 3, method: "tools/call", params: { name: "berekenAktekstn" } },
      ORIGIN,
    );
    expect(antwoord?.error?.code).toBe(-32602);
    // "bedoelde je …?"-suggestie voor de dichtstbijzijnde bestaande toolnaam.
    expect(antwoord?.error?.message).toContain("berekenAktekosten");
  });

  it("tools/call zonder 'name' geeft -32602", async () => {
    const antwoord = await verwerkBericht(
      { jsonrpc: "2.0", id: 4, method: "tools/call", params: {} },
      ORIGIN,
    );
    expect(antwoord?.error?.code).toBe(-32602);
  });

  it("tools/call met niet-object 'arguments' geeft -32602", async () => {
    const antwoord = await verwerkBericht(
      {
        jsonrpc: "2.0",
        id: 5,
        method: "tools/call",
        params: { name: "berekenAktekosten", arguments: "geen-object" },
      },
      ORIGIN,
    );
    expect(antwoord?.error?.code).toBe(-32602);
  });

  it("een onbekende methode geeft -32601, maar een notificatie wordt stil genegeerd", async () => {
    const fout = await verwerkBericht({ jsonrpc: "2.0", id: 6, method: "doesNotExist" }, ORIGIN);
    expect(fout?.error?.code).toBe(-32601);
    const notificatie = await verwerkBericht({ jsonrpc: "2.0", method: "notifications/initialized" }, ORIGIN);
    expect(notificatie).toBeNull();
  });
});
