"""A/B V1 vs V2 — schéma COMPLET comme base (ancrage maximal)."""
import json
import time
from pathlib import Path
from pipeline.ocr_glm import GLMOCR
from pipeline.ingest import pdf_to_images
from pipeline.extract import parse_json_output
from pipeline.prompts import SCHEMA_RECUEIL as PROMPT_V1_CURRENT


PROMPT_V2 = """Lis cette fiche médicale OGC (contrôle T2A Assurance Maladie) et renvoie STRICTEMENT le JSON ci-dessous, sans commentaire ni markdown.

CONSIGNES IMPORTANTES :
- Le tableau "Codage de l'Établissement / Recodage" a DEUX colonnes distinctes : les codes "Recodage" sont dans la colonne la plus à DROITE, visuellement séparés des codes "Établissement" (à gauche). Ne recopie JAMAIS les codes Établissement dans Recodage. Si la colonne Recodage est vide, laisse vide.
- "dp_libelle" = texte descriptif majuscules qui suit le code DP sur la même ligne (ex: "HEMORR. ET HEMATOME COMPLIQ. UN ACTE, NCA").
- Les 4 valeurs GHM/GHS sont sur UNE SEULE LIGNE en bas, lisibles dans cet ordre : "GHM établissement : XXX   GHS établissement : YYY   GHM après recodage : ZZZ   GHS après recodage : WWW". Extrais les 4 séparément.
- "praticien_conseil" = nom manuscrit (forme "DR + NOM") tout en bas de page, sous "Nom du praticien conseil responsable du codage".
- Les codes CIM-10 commencent TOUJOURS par une LETTRE majuscule (A-Z) suivie de chiffres. JAMAIS par un chiffre. Ex : "I652", "K650", "T814" — jamais "1652".
- Les codes GHM : 2 chiffres + lettre + 3 chiffres (ex: "11M122", "06M033").
- Les codes GHS : nombre à 3-5 chiffres (ex: "4323", "863").
- Si un champ est illisible ou absent, laisse une chaîne vide. Ne devine pas.

{
  "etablissement": "",
  "finess": "",
  "date_debut_controle": "",
  "n_ogc": "",
  "n_champ": "",
  "dates_sejour": "",
  "sejour_etab": {
    "age": "", "sexe": "", "duree_sejour": "",
    "mode_entree": "", "provenance": "",
    "mode_sortie": "", "destination": ""
  },
  "sejour_reco": {
    "age": "", "sexe": "", "duree_sejour": "",
    "mode_entree": "", "provenance": "",
    "mode_sortie": "", "destination": ""
  },
  "rum_etab": {"um": "", "igs": "", "duree": "", "dates": ""},
  "codage_etab": {
    "dp": "", "dp_libelle": "", "dr": "",
    "das": [{"code": "", "position": "", "libelle": ""}]
  },
  "codage_reco": {
    "dp": "", "dr": "",
    "das": [{"code": "", "position": ""}]
  },
  "actes_etab": [{"code": "", "position": "", "libelle": ""}],
  "actes_reco": [{"code": "", "position": ""}],
  "ghm_etab": "", "ghs_etab": "",
  "ghm_reco": "", "ghs_reco": "",
  "recodage_impactant": "",
  "ghs_injustifie": "",
  "praticien_conseil": ""
}"""


CASES = [("2018 CARC/OGC 7.pdf",1), ("2018 CARC/OGC 27.pdf",1), ("2018 CARC/OGC 55.pdf",1), ("2018 CARC/OGC 86.pdf",1)]
TARGETS = ["codage_etab.dp", "codage_etab.dp_libelle", "codage_reco.dp",
           "ghm_etab", "ghs_etab", "ghm_reco", "ghs_reco", "praticien_conseil"]


def get(d, path):
    for k in path.split("."):
        d = d.get(k, "") if isinstance(d, dict) else ""
    return str(d).strip()


def run_prompt(label, prompt, ocr):
    print(f"\n### {label}")
    scores = {f: 0 for f in TARGETS}
    totals = {f: 0 for f in TARGETS}
    for pdf, page in CASES:
        name = Path(pdf).stem
        img = pdf_to_images(pdf)[page-1]
        with open(f"output/{name}.json") as f: legacy = json.load(f)["recueil"]["parsed"]
        t0 = time.time()
        res = ocr.run(img, prompt, max_new_tokens=4096)
        parsed = parse_json_output(res["text"]) or {}
        print(f"  {name} ({time.time()-t0:.1f}s)")
        for tf in TARGETS:
            v_ext = get(parsed, tf)
            v_leg = get(legacy, tf)
            # Tolérance dp_libelle : accepter inclusion
            if tf == "codage_etab.dp_libelle":
                match = v_leg in v_ext if (v_ext and v_leg) else (v_ext == v_leg)
            else:
                match = v_ext == v_leg
            if v_leg:  # ne compter que les champs où legacy a une valeur
                totals[tf] += 1
                if match: scores[tf] += 1
            mark = "✓" if match else ("∅" if not v_ext and not v_leg else "✗")
            if tf in ("codage_reco.dp", "ghs_reco", "praticien_conseil", "codage_etab.dp_libelle"):
                print(f"    {mark} {tf:26s} ext={v_ext!r:40s} leg={v_leg!r}")
    print(f"  --- Score par champ (vs legacy si renseigné) ---")
    for tf in TARGETS:
        print(f"    {tf:26s}: {scores[tf]}/{totals[tf]}")
    return scores, totals


def main():
    ocr = GLMOCR()
    print(f"VRAM = {ocr.vram_gb:.2f} Go")
    s1, t1 = run_prompt("V1 (schéma actuel)", PROMPT_V1_CURRENT, ocr)
    s2, t2 = run_prompt("V2 (consignes précises)", PROMPT_V2, ocr)
    print("\n=========== DELTA V2 - V1 ===========")
    for tf in TARGETS:
        d = s2[tf] - s1[tf]
        mark = "+" if d > 0 else ("-" if d < 0 else "=")
        print(f"  {mark} {tf:26s} V1={s1[tf]}/{t1[tf]} → V2={s2[tf]}/{t2[tf]}")


if __name__ == "__main__":
    main()
