import { expect, test } from "bun:test";
import {
  buildLlmDossier,
  createPseudonymizer,
  reversePseudonymsInText,
  reversePseudonymsInDossier,
} from "./privacy";
import type { LlmDossier, SummaryData } from "./privacy";

const sample: SummaryData = {
  kontakt: {
    unternehmen: {
      name: "Muster GmbH",
      adresse: "Hauptstrasse 1",
      plz: "80331 Muenchen",
      telefon: "+49 89 123456",
      email: "kontakt@muster.de",
      web: "www.muster.de",
    },
    ansprechpartner: {
      name: "Max Mustermann",
      telefon: "0170 1234567",
      email: "max.mustermann@muster.de",
    },
  },
  unternehmen: {
    branche: "Maschinenbau",
    gruendungsjahr: "1998",
    anzahl_mitarbeiter: "120",
    interne_notiz: "Nicht fuer LLM",
  },
  fragen: {
    frage1: {
      label: "Frage 1",
      antwort: "Max Mustermann beschreibt die Entwicklung der Muster GmbH. Muster investiert weiter. Kontakt: max.mustermann@muster.de.",
      fragen: [
        {
          id: "frage1_1",
          text: "Was macht das Unternehmen aus?",
          antwort: "Die Muster GmbH ist unter +49 89 123456 erreichbar.",
        },
      ],
    },
  },
  kriterium: {
    robustheit_resilienz: {
      label: "Robustheit",
      antwort: "Die Muster GmbH hat ein Risikomanagement etabliert. Muster nutzt Fruehwarnprozesse.",
    },
  },
};

test("builds a minimized dossier without contact data or unknown company fields", () => {
  const dossier = buildLlmDossier(sample);
  const serialized = JSON.stringify(dossier);

  expect(dossier.unternehmen).toEqual({
    branche: "Maschinenbau",
    gruendungsjahr: "1998",
    anzahl_mitarbeiter: "120",
  });
  expect(serialized).not.toContain("kontakt");
  expect(serialized).not.toContain("interne_notiz");
  expect(serialized).not.toContain("Hauptstrasse");
});

test("pseudonymizes known personal and contact values in LLM-bound strings", () => {
  const privacy = createPseudonymizer(sample);
  const prepared = privacy.pseudonymizeDossier(buildLlmDossier(sample));
  const serialized = JSON.stringify(prepared.safe);

  expect(serialized).toContain("[PERSON_1]");
  expect(serialized).toContain("[UNTERNEHMEN]");
  expect(serialized).toContain("[EMAIL_2]");
  expect(serialized).toContain("[TELEFON_1]");
  expect(serialized).not.toContain("Max Mustermann");
  expect(serialized).not.toContain("Muster GmbH");
  expect(serialized).not.toContain("Muster investiert");
  expect(serialized).not.toContain("Muster nutzt");
  expect(serialized).not.toContain("max.mustermann@muster.de");
  expect(prepared.audit.mode).toBe("minimized+pseudonymized");
  expect(prepared.audit.companyName).toBe("Muster GmbH");
  expect(prepared.audit.replacements.length).toBeGreaterThan(0);
});

test("reversePseudonymsInText restores original values from known replacements", () => {
  const text = "[PERSON_1] von [UNTERNEHMEN] nutzt [EMAIL_2].";
  const reversed = reversePseudonymsInText(text, [
    { value: "Max Mustermann", type: "person", placeholder: "[PERSON_1]" },
    { value: "Muster GmbH", type: "company", placeholder: "[UNTERNEHMEN]" },
    { value: "max.mustermann@muster.de", type: "email", placeholder: "[EMAIL_2]" },
  ]);

  expect(reversed).toBe("Max Mustermann von Muster GmbH nutzt max.mustermann@muster.de.");
});

test("reversePseudonyms works via the Pseudonymizer API", () => {
  const privacy = createPseudonymizer(sample);
  const reversed = privacy.reversePseudonyms("[PERSON_1] arbeitet bei [UNTERNEHMEN].");

  expect(reversed).toContain("Max Mustermann");
  expect(reversed).toContain("Muster GmbH");
});

test("reversePseudonymsInText handles text without placeholders", () => {
  const text = "Kein Platzhalter hier.";
  const reversed = reversePseudonymsInText(text, [
    { value: "Max Mustermann", type: "person", placeholder: "[PERSON_1]" },
  ]);
  expect(reversed).toBe(text);
});

test("reversePseudonymsInDossier reverses nested text fields including zusammenfassung", () => {
  const dossier: LlmDossier = {
    fragen: {
      frage1: {
        label: "[PERSON_1] von [UNTERNEHMEN] beantwortet",
        zusammenfassung: "[PERSON_1] arbeitet bei [UNTERNEHMEN] und nutzt [EMAIL_2].",
        fragen: [
          { id: "f1", text: "Was macht [UNTERNEHMEN]?", antwort: "[PERSON_1] sagt [EMAIL_2]." },
        ],
      },
    },
    kriterium: {
      robustheit: {
        label: "Robustheit von [PERSON_1]",
        zusammenfassung: "[UNTERNEHMEN] ist robust.",
      },
    },
    unternehmen: {
      referenzen: "Referenz von [PERSON_1] bei [UNTERNEHMEN].",
    },
  };

  const reversed = reversePseudonymsInDossier(dossier, [
    { value: "Max Mustermann", type: "person", placeholder: "[PERSON_1]" },
    { value: "Muster GmbH", type: "company", placeholder: "[UNTERNEHMEN]" },
    { value: "max@muster.de", type: "email", placeholder: "[EMAIL_2]" },
  ]);

  expect(reversed.fragen?.frage1?.zusammenfassung).toBe(
    "Max Mustermann arbeitet bei Muster GmbH und nutzt max@muster.de.",
  );
  expect(reversed.fragen?.frage1?.fragen?.[0]?.antwort).toBe(
    "Max Mustermann sagt max@muster.de.",
  );
  expect(reversed.fragen?.frage1?.label).toBe(
    "Max Mustermann von Muster GmbH beantwortet",
  );
  expect(reversed.kriterium?.robustheit?.zusammenfassung).toBe(
    "Muster GmbH ist robust.",
  );
  expect(reversed.unternehmen?.referenzen).toBe(
    "Referenz von Max Mustermann bei Muster GmbH.",
  );
});

test("reversePseudonymsInText handles edge case with numeric suffixes in text", () => {
  const text = "[PERSON_1] und [PERSON_1].";
  const reversed = reversePseudonymsInText(text, [
    { value: "Max Mustermann", type: "person", placeholder: "[PERSON_1]" },
  ]);
  expect(reversed).toBe("Max Mustermann und Max Mustermann.");
});
