"""Generiert src/services/umlaut_dict.json aus hunspell-de-de.

Aufruf (auf dem Monitor-Server):
    cd /home/claude-dev/AegisSight-Monitor
    python3 scripts/build_umlaut_dict.py

Voraussetzungen:
    - hunspell-de-de (liefert /usr/share/hunspell/de_DE.dic + de_DE.aff)
    - hunspell-tools (liefert /usr/bin/unmunch)

Ablauf:
    1. unmunch rollt alle Flexionsformen aus dem hunspell-Dict aus
    2. Wir filtern Woerter mit echten Umlauten (ä, ö, ü, ß)
    3. Wir generieren fuer jedes Wort die Umschreibungs-Form (ae/oe/ue/ss)
    4. Mehrdeutigkeits-Check: Wenn die Umschreibungs-Form selbst ein
       gueltiges deutsches Wort ist (z. B. "dass" vs "daß"), skippen
    5. Ausgabe als alphabetisch sortiertes JSON (diff-freundlich)
"""
import json
import locale
import os
import subprocess
import sys

DIC_PATH = "/usr/share/hunspell/de_DE.dic"
AFF_PATH = "/usr/share/hunspell/de_DE.aff"
UNMUNCH_BIN = "/usr/bin/unmunch"

OUTPUT_PATH = os.path.join(
    os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
    "src", "services", "umlaut_dict.json",
)

UMLAUT_MAP = (
    ("ä", "ae"), ("ö", "oe"), ("ü", "ue"), ("ß", "ss"),
    ("Ä", "Ae"), ("Ö", "Oe"), ("Ü", "Ue"),
)


def to_ascii_form(word: str) -> str:
    """Konvertiert ein Wort mit Umlauten in seine Umschreibungs-Form."""
    out = word
    for uml, asc in UMLAUT_MAP:
        out = out.replace(uml, asc)
    return out


def has_umlaut(word: str) -> bool:
    return any(ch in word for ch in "äöüßÄÖÜ")


def run_unmunch() -> set:
    """Fuehrt unmunch aus und gibt die Menge aller hunspell-Woerter zurueck."""
    env = os.environ.copy()
    # unmunch arbeitet mit Latin-1 als Voreinstellung; das .dic/.aff in de_DE
    # ist aber UTF-8 (siehe SET UTF-8 im .aff). Wir setzen die Locale explizit.
    env["LC_ALL"] = "C.UTF-8"
    result = subprocess.run(
        [UNMUNCH_BIN, DIC_PATH, AFF_PATH],
        capture_output=True,
        check=True,
        env=env,
    )
    raw = result.stdout.decode("utf-8", errors="replace")
    words = set()
    for line in raw.splitlines():
        w = line.strip()
        if not w or w.startswith("#"):
            continue
        words.add(w)
    return words


def build_mapping(all_words: set) -> tuple[dict, int, int]:
    """Baut das Umlaut-Ersetzungs-Mapping.

    Rueckgabe: (mapping, skipped_ambiguous, words_with_umlaut)
    """
    mapping = {}
    skipped_ambiguous = 0
    words_with_umlaut = 0

    for word in all_words:
        if not has_umlaut(word):
            continue
        words_with_umlaut += 1

        ascii_form = to_ascii_form(word)
        # Mehrdeutigkeits-Check: Umschreibung ist selbst ein gueltiges Wort?
        if ascii_form in all_words:
            skipped_ambiguous += 1
            continue

        # Standardfall: Mapping Umschreibung -> Umlaut-Form
        mapping[ascii_form] = word

        # Zusaetzlich Capitalize-Variante erzeugen (wenn anders als Original)
        if ascii_form[:1].islower():
            cap_ascii = ascii_form[:1].upper() + ascii_form[1:]
            cap_umlaut = word[:1].upper() + word[1:]
            if cap_ascii != ascii_form and cap_ascii not in all_words:
                mapping[cap_ascii] = cap_umlaut

    return mapping, skipped_ambiguous, words_with_umlaut


def sanity_spot_check(mapping: dict) -> None:
    """Prueft ob einige typische Testfaelle korrekt im Mapping abgebildet sind."""
    expected_in = [
        "oeffnung", "Oeffnung", "strasse", "Strasse", "fuer", "Fuer",
        "ueber", "Ueber", "koennen", "Koennen", "muessen", "Muessen",
        "moeglich", "Moeglich", "schliessen", "Schliessen",
        "aussenminister", "Aussenminister", "praesident", "Praesident",
        "buerger", "Buerger", "zurueck", "Zurueck", "fuehren", "Fuehren",
    ]
    expected_not_in = [
        "dass", "Dass",         # moderne Form gueltig
        "masse", "Masse",       # Bedeutungsunterschied zu "Masse"/"Maße"
        "busse", "Busse",       # Bedeutungsunterschied zu "Busse"/"Buße"
    ]
    missing = [w for w in expected_in if w not in mapping]
    wrong = [w for w in expected_not_in if w in mapping]
    print("Sanity-Check:")
    print(f"  Erwartete Eintraege gefunden: {len(expected_in) - len(missing)}/{len(expected_in)}")
    if missing:
        print(f"    FEHLEND: {missing}")
    print(f"  Erwartete Ausschluesse korrekt: {len(expected_not_in) - len(wrong)}/{len(expected_not_in)}")
    if wrong:
        print(f"    FAELSCHLICH DRIN: {wrong}")


def main():
    if not os.path.exists(DIC_PATH):
        print(f"FEHLER: {DIC_PATH} nicht gefunden. Paket hunspell-de-de installiert?",
              file=sys.stderr)
        sys.exit(1)
    if not os.path.exists(UNMUNCH_BIN):
        print(f"FEHLER: {UNMUNCH_BIN} nicht gefunden. Paket hunspell-tools installiert?",
              file=sys.stderr)
        sys.exit(1)

    print(f"Lese hunspell-Dict via {UNMUNCH_BIN} ...")
    all_words = run_unmunch()
    print(f"  {len(all_words)} hunspell-Wortformen geladen")

    print("Baue Umlaut-Ersetzungs-Mapping ...")
    mapping, skipped, umlaut_words = build_mapping(all_words)
    print(f"  {umlaut_words} Woerter mit Umlaut gefunden")
    print(f"  {skipped} mehrdeutige Formen uebersprungen (z.B. dass/daß)")
    print(f"  {len(mapping)} Eintraege im finalen Mapping")

    sanity_spot_check(mapping)

    print(f"\nSchreibe {OUTPUT_PATH} ...")
    os.makedirs(os.path.dirname(OUTPUT_PATH), exist_ok=True)
    # Alphabetisch sortiert (diff-freundlich)
    sorted_mapping = dict(sorted(mapping.items(), key=lambda kv: kv[0]))
    with open(OUTPUT_PATH, "w", encoding="utf-8") as f:
        json.dump(sorted_mapping, f, ensure_ascii=False, indent=None, separators=(",", ":"))
    size_mb = os.path.getsize(OUTPUT_PATH) / (1024 * 1024)
    print(f"  {size_mb:.2f} MB geschrieben")
    print("Fertig.")


if __name__ == "__main__":
    main()
