#!/usr/bin/env python3
"""
Validation du gazetteer paranames (Wikidata CC BY 4.0).

Vérifie que le fichier `data/paranames/noms_famille_world.txt.gz` est :
1. Présent et lisible
2. Contient les noms tests internationaux (OYARCABAL, EJNAINI, ...)
3. Contient les noms INSEE FR courants (overlap)
4. Ne contient PAS de mots français courants (risque FP)
5. Améliore la détection sur audit_30 (si les PDFs sont disponibles)

Usage : python scripts/validate_paranames.py
Le script s'arrête immédiatement si le fichier n'existe pas.
"""
from __future__ import annotations

import gzip
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]
DATA_DIR = ROOT / "data" / "paranames"
GAZETTEER_PATH = DATA_DIR / "noms_famille_world.txt.gz"

# Noms tests internationaux — doivent être présents
NOMS_TESTS = {
    "EJNAINI",     # maghrébin
    "NGUYEN",      # vietnamien
    "SCHMIDT",     # germanique
    "OBAMA",       # africain
    "NAKAMURA",    # japonais
    "SINGH",       # indien
    "TANAKA",      # japonais
    "GARCIA",      # hispanique
    "ROSSI",       # italien
}

# Noms couverts par un autre mécanisme que le gazetteer (regex F2/F3 « Nom usuel »).
# Leur absence de paranames est informative, pas bloquante.
NOMS_COUVERTS_AILLEURS = {
    "OYARCABAL": "regex F3 (label « Nom usuel : ») — absent du dump Wikidata",
}

# Noms INSEE FR courants — overlap attendu
NOMS_INSEE_FR = {"MARTIN", "BERNARD", "DUBOIS", "THOMAS", "PETIT", "ROBERT", "RICHARD"}

# Mots-outils français — NE doivent PAS être présents (filtrés via stopwords_manuels).
# NB : on n'y met QUE des mots-outils sans risque d'être un patronyme. Des mots
# comme « allez » ou « polygone » SONT de vrais patronymes INSEE rares : on les
# garde masquables (priorité sécurité = pas de fuite), donc hors de cette liste.
MOTS_FR_INTERDITS = {"VOIR", "MIDI", "SANS", "AVEC", "POUR", "DANS"}


def status(icon: str, label: str, ok: bool, detail: str = "") -> str:
    tag = "✅ OK" if ok else "❌ FAIL"
    d = f" — {detail}" if detail else ""
    return f"{icon} [{tag}] {label}{d}"


def main() -> int:
    print("=" * 60)
    print("  VALIDATION GAZETTEER PARANAMES")
    print("=" * 60)

    # Check 0: fichier présent
    if not GAZETTEER_PATH.exists():
        print(f"\n❌ Fichier absent : {GAZETTEER_PATH}")
        print("Le gazetteer paranames n'a pas encore été généré.")
        print("Relancer quand data/paranames/noms_famille_world.txt.gz existe.")
        return 1

    # Load
    print(f"\n📂 Chargement : {GAZETTEER_PATH}")
    with gzip.open(GAZETTEER_PATH, "rt", encoding="utf-8") as f:
        noms = {line.strip().upper() for line in f if line.strip()}

    print(f"   {len(noms):,} noms chargés")

    results = {}

    # Check 1: taille minimale
    min_size = 100_000
    ok = len(noms) >= min_size
    results["taille"] = ok
    print(status("📊", f"Taille ≥ {min_size:,}", ok, f"{len(noms):,} noms"))

    # Check 2: noms tests internationaux
    presents = {n for n in NOMS_TESTS if n in noms}
    absents = NOMS_TESTS - presents
    ok = len(absents) == 0
    results["noms_tests"] = ok
    if absents:
        print(status("🌍", "Noms tests internationaux", ok, f"absents: {sorted(absents)}"))
    else:
        print(status("🌍", "Noms tests internationaux", ok, f"{len(presents)}/{len(NOMS_TESTS)} présents"))

    # Check 2bis : noms couverts par un autre mécanisme (warning informatif, non bloquant)
    for nom, mecanisme in sorted(NOMS_COUVERTS_AILLEURS.items()):
        present = nom in noms
        tag = "présent" if present else "absent (attendu)"
        print(f"ℹ️  [WARN] {nom} : {tag} de paranames — couvert par {mecanisme}")

    # Check 3: overlap INSEE FR
    overlap = {n for n in NOMS_INSEE_FR if n in noms}
    ok = len(overlap) >= len(NOMS_INSEE_FR) - 1  # tolère 1 manquant
    results["overlap_insee"] = ok
    print(status("🇫🇷", "Overlap INSEE FR", ok, f"{len(overlap)}/{len(NOMS_INSEE_FR)}"))

    # Check 4: pas de mots français courants
    interdits_trouves = {m for m in MOTS_FR_INTERDITS if m in noms}
    ok = len(interdits_trouves) == 0
    results["pas_mots_fr"] = ok
    if interdits_trouves:
        print(status("🚫", "Pas de mots FR courants", ok, f"trouvés: {sorted(interdits_trouves)}"))
    else:
        print(status("🚫", "Pas de mots FR courants", ok))

    # Check 5: effet sur audit_30 (si PDFs disponibles)
    pdfs_dir = ROOT / "pdf_natif"
    if not pdfs_dir.exists() or not list(pdfs_dir.glob("*.pdf")):
        results["audit30"] = None  # N/A
        print(status("📄", "Test audit_30", True, "PDFs non disponibles — SKIP"))
    else:
        # Quick check: essayer de charger le gazetteer via le core
        try:
            sys.path.insert(0, str(ROOT))
            from anonymizer_core_refactored_onnx import _load_paranames_noms, _PARANAMES_NOMS_SET
            loaded = _load_paranames_noms()
            ok = len(loaded) > 0
            results["audit30"] = ok
            print(status("⚙️", "Chargement core OK", ok, f"{len(loaded):,} noms dans le core"))

            # Vérifier que les noms gazetteer attendus sont reconnus
            for test_nom in ["EJNAINI", "NGUYEN"]:
                in_core = test_nom.upper() in loaded
                print(status(f"  {test_nom}", "Reconnu dans core", in_core))
        except Exception as e:
            results["audit30"] = False
            print(status("⚙️", "Chargement core", False, str(e)))

    # Summary
    print("\n" + "=" * 60)
    passed = sum(1 for v in results.values() if v is True)
    failed = sum(1 for v in results.values() if v is False)
    skipped = sum(1 for v in results.values() if v is None)
    print(f"  {passed} passed, {failed} failed, {skipped} skipped")
    if failed > 0:
        print("  ⚠️  Gazetteer nécessite corrections avant utilisation.")
        return 1
    print("  ✅ Gazetteer paranames validé.")
    return 0


if __name__ == "__main__":
    sys.exit(main())
