/**
 * Tests für mail-training-utils.ts — Phase 1 Data-Foundation.
 *
 * Abgedeckt:
 *   - sanitizeSubjectForTraining() — alle Regex-Patterns
 *   - detectSubjectLanguage() — franc-Integration
 *   - Edge-Cases: null, leer, nur Whitespace
 */
import { describe, it, expect } from "vitest";

import {
  sanitizeSubjectForTraining,
  detectSubjectLanguage,
} from "../../server/utils/mail-training-utils";

// ─── sanitizeSubjectForTraining() ─────────────────────────────────────────────

describe("sanitizeSubjectForTraining()", () => {
  // ─── Edge-Cases ────────────────────────────────────────────────────────────

  it("null → leerer String + detectedLang='und'", () => {
    const result = sanitizeSubjectForTraining(null);
    expect(result.subjectSanitized).toBe("");
    expect(result.detectedLang).toBe("und");
  });

  it("leerer String → leerer String + detectedLang='und'", () => {
    const result = sanitizeSubjectForTraining("");
    expect(result.subjectSanitized).toBe("");
    expect(result.detectedLang).toBe("und");
  });

  it("nur Whitespace → leerer String", () => {
    const result = sanitizeSubjectForTraining("   ");
    expect(result.subjectSanitized).toBe("");
  });

  // ─── E-Mail-Erkennung ──────────────────────────────────────────────────────

  it("E-Mail-Adresse im Betreff → [EMAIL]", () => {
    const result = sanitizeSubjectForTraining("Info für test@example.com");
    expect(result.subjectSanitized).toBe("Info für [EMAIL]");
  });

  it("E-Mail mitten im Satz → [EMAIL]", () => {
    const result = sanitizeSubjectForTraining("Willkommen user123@domain.de, dein Konto ist aktiv");
    expect(result.subjectSanitized).toBe("Willkommen [EMAIL], dein Konto ist aktiv");
  });

  // ─── URL-Erkennung ─────────────────────────────────────────────────────────

  it("https-URL → [URL]", () => {
    const result = sanitizeSubjectForTraining("Besuche https://casino.bet/promo");
    expect(result.subjectSanitized).toBe("Besuche [URL]");
  });

  it("http-URL → [URL]", () => {
    const result = sanitizeSubjectForTraining("Klicke auf http://example.com/offer");
    expect(result.subjectSanitized).toBe("Klicke auf [URL]");
  });

  it("www-URL → [URL]", () => {
    const result = sanitizeSubjectForTraining("www.bonus.de/angebot jetzt sichern");
    expect(result.subjectSanitized).toBe("[URL] jetzt sichern");
  });

  // ─── Zahlen-Erkennung ──────────────────────────────────────────────────────

  it("5-stellige Zahl → [NUM]", () => {
    const result = sanitizeSubjectForTraining("Bestellung 12345 wurde versandt");
    expect(result.subjectSanitized).toBe("Bestellung [NUM] wurde versandt");
  });

  it("9-stellige Kundennummer → [NUM]", () => {
    const result = sanitizeSubjectForTraining("Deine Kundennummer: 987654321");
    expect(result.subjectSanitized).toBe("Deine Kundennummer: [NUM]");
  });

  it("4-stellige Zahl bleibt erhalten (Jahr, Score)", () => {
    const result = sanitizeSubjectForTraining("Angebot 2024 — bis zu 1000€");
    expect(result.subjectSanitized).toBe("Angebot 2024 — bis zu 1000€");
  });

  // ─── Greeting-Prefix ───────────────────────────────────────────────────────

  it("'Hallo Max, ...' → Greeting-Prefix stripped", () => {
    const result = sanitizeSubjectForTraining("Hallo Max, dein Bonus wartet");
    expect(result.subjectSanitized).toBe("dein Bonus wartet");
  });

  it("'Hi Sarah! ...' → Greeting-Prefix stripped", () => {
    const result = sanitizeSubjectForTraining("Hi Sarah! Neues Angebot für dich");
    expect(result.subjectSanitized).toBe("Neues Angebot für dich");
  });

  it("'Dear John, ...' → Greeting-Prefix stripped", () => {
    const result = sanitizeSubjectForTraining("Dear John, your account is ready");
    expect(result.subjectSanitized).toBe("your account is ready");
  });

  it("'Cher Michel, ...' → Greeting-Prefix stripped", () => {
    const result = sanitizeSubjectForTraining("Cher Michel, votre offre expire");
    expect(result.subjectSanitized).toBe("votre offre expire");
  });

  it("kein Greeting → bleibt unverändert (kein false strip)", () => {
    const result = sanitizeSubjectForTraining("Casino Bonus wartet auf dich");
    expect(result.subjectSanitized).toBe("Casino Bonus wartet auf dich");
  });

  // ─── ALL-CAPS-Wörter ───────────────────────────────────────────────────────

  it("ALL-CAPS-Wort >= 4 Zeichen → [NAME]", () => {
    const result = sanitizeSubjectForTraining("Willkommen HANS, dein Konto ist bereit");
    expect(result.subjectSanitized).toBe("Willkommen [NAME], dein Konto ist bereit");
  });

  it("ALL-CAPS-Wort < 4 Zeichen bleibt (z.B. 'SMS', 'VIP')", () => {
    const result = sanitizeSubjectForTraining("Dein VIP-Bonus wartet");
    // "VIP" ist 3 Zeichen → bleibt erhalten
    expect(result.subjectSanitized).toBe("Dein VIP-Bonus wartet");
  });

  // ─── Whitespace-Normalisierung ─────────────────────────────────────────────

  it("mehrfache Leerzeichen nach Sanitization → normalisiert", () => {
    // Wenn Greeting entfernt wird können führende Leerzeichen entstehen
    const result = sanitizeSubjectForTraining("Hallo   Test,  dein Angebot");
    expect(result.subjectSanitized).not.toMatch(/\s{2,}/);
  });

  // ─── Kombinierte Patterns ──────────────────────────────────────────────────

  it("Kombination: URL + Zahl + E-Mail alle ersetzt", () => {
    const result = sanitizeSubjectForTraining(
      "Tracking 123456789: Paket von user@shop.de — Link: https://track.shop.de/abc"
    );
    expect(result.subjectSanitized).toContain("[NUM]");
    expect(result.subjectSanitized).toContain("[EMAIL]");
    expect(result.subjectSanitized).toContain("[URL]");
    expect(result.subjectSanitized).not.toMatch(/\d{5,}/);
    expect(result.subjectSanitized).not.toMatch(/[a-zA-Z0-9._%+\-]+@/);
  });

  it("realistisches Gambling-Mail bleibt erkennbar nach Sanitization", () => {
    const result = sanitizeSubjectForTraining(
      "Dein Glücksspiel-Bonus 100€ wartet — Tracking: 987654321"
    );
    // Gambling-Signal "Glücksspiel-Bonus" bleibt erhalten
    expect(result.subjectSanitized).toContain("Glücksspiel-Bonus");
    // Tracking-ID wird ersetzt
    expect(result.subjectSanitized).toContain("[NUM]");
    expect(result.subjectSanitized).not.toMatch(/\d{5,}/);
  });
});

// ─── detectSubjectLanguage() ──────────────────────────────────────────────────

describe("detectSubjectLanguage()", () => {
  it("null → 'und'", () => {
    expect(detectSubjectLanguage(null)).toBe("und");
  });

  it("leerer String → 'und'", () => {
    expect(detectSubjectLanguage("")).toBe("und");
  });

  it("Deutsch erkannt (deu)", () => {
    // Längerer Text für bessere Spracherkennung
    const lang = detectSubjectLanguage(
      "Dein exklusives Angebot wartet auf dich — jetzt einlösen und profitieren"
    );
    expect(lang).toBe("deu");
  });

  it("Englisch-artiger Text → nicht 'und' (franc erkennt eine Sprache)", () => {
    // franc kann je nach Text-Sample eng oder sco (Scots) zurückgeben für englische Texte —
    // beide sind akzeptabel. Wichtig: kein "und" (= unbekannt).
    const lang = detectSubjectLanguage(
      "Your exclusive offer is waiting — claim your bonus now and start winning today"
    );
    expect(lang).not.toBe("und");
    expect(typeof lang).toBe("string");
  });

  it("Zu kurzer Text → 'und' (franc-Limitation bei < ~20 Zeichen)", () => {
    // Sehr kurze Texte liefern "und" oder falsche Erkennungen — erwartetes Verhalten.
    // Wir prüfen nur dass ein String zurückkommt (kein throw).
    const lang = detectSubjectLanguage("Hi");
    expect(typeof lang).toBe("string");
    expect(lang.length).toBeGreaterThan(0);
  });
});
