#!/usr/bin/env python3
"""Extrait les rapports JSON bruts (stdout du test ignoré) et produit synthese.json + synthese.csv."""
import csv, json, pathlib, sys
D = pathlib.Path(__file__).resolve().parent

def extract(path):
    txt = path.read_text()
    start = txt.find('{\n  "schema"')
    depth = 0
    for i in range(start, len(txt)):
        c = txt[i]
        if c == "{": depth += 1
        elif c == "}":
            depth -= 1
            if depth == 0:
                return json.loads(txt[start:i + 1])
    raise ValueError(path)

rows = []
for f in sorted(D.glob("*.stdout.txt")):
    try:
        r = extract(f)
    except Exception as e:
        print("SKIP", f.name, e, file=sys.stderr); continue
    (D / f.name.replace(".stdout.txt", ".report.json")).write_text(json.dumps(r, ensure_ascii=False, indent=2))
    s, c = r["summary"], r["summary"]["calibration"]
    meta = (D / f.name.replace(".stdout.txt", ".meta.txt")).read_text().split()[1].split("=")[1]
    rows.append({
        "model": r["model"]["model"], "params": r["model"]["parameter_size"], "quant": r["model"]["quantization"],
        "digest": r["model"]["digest_prefix"], "ollama": r["ollama_version"], "status": r["status"],
        "games": s["games"], "wins": s["wins"], "win_ci_low": s["win_rate_ci95_low"], "win_ci_high": s["win_rate_ci95_high"],
        "treasure": s["treasure_pickups"], "outcomes": s["outcomes"], "mean_rounds": s["mean_rounds"],
        "llm_calls": s["llm_calls"], "invalid": s["invalid_responses"], "invalid_by_reason": s.get("invalid_by_reason"),
        "forced_passes": s["forced_passes"], "timed_out_calls": s.get("timed_out_calls"), "timeout_rate": s.get("timeout_rate"),
        "perturbed": s.get("measurement_perturbed"), "warmup": r.get("warmup"),
        "mean_latency_ms": s["mean_latency_ms"], "known_wall_repeats": s["known_wall_repeats"], "mean_bumps": s["mean_bumps"],
        "samples": c["samples"], "mean_conf": c["mean_confidence"], "move_success": c["observed_move_success_rate"],
        "move_ci_low": c.get("observed_rate_ci95_low"), "move_ci_high": c.get("observed_rate_ci95_high"),
        "brier": c["brier_score"], "ece": c.get("ece"), "ece_ci_low": c.get("ece_ci95_low"), "ece_ci_high": c.get("ece_ci95_high"),
        "resolution": (c.get("murphy") or {}).get("resolution"), "reliability": (c.get("murphy") or {}).get("reliability"),
        "uncertainty": (c.get("murphy") or {}).get("uncertainty"),
        "bins": [{k: b[k] for k in ("lower", "upper", "samples", "mean_confidence", "observed_rate", "observed_rate_ci95_low", "observed_rate_ci95_high", "sufficient")} for b in c.get("reliability_bins", [])],
        "plain": c.get("plain_language_fr"), "wall_seconds": int(meta), "report_sha256": r["report_sha256"],
        "evidence": [g["evidence_sha256"][:12] for g in r["games"]],
        "game_outcomes": [g["outcome"] for g in r["games"]],
    })
(D / "synthese.json").write_text(json.dumps(rows, ensure_ascii=False, indent=2))
keys = [k for k in rows[0] if k not in ("bins", "outcomes", "invalid_by_reason", "warmup", "evidence", "game_outcomes", "plain")] if rows else []
with open(D / "synthese.csv", "w", newline="") as fh:
    w = csv.DictWriter(fh, fieldnames=keys, extrasaction="ignore"); w.writeheader(); [w.writerow(x) for x in rows]
for x in rows:
    print(x["model"], x["params"], f'{x["wins"]}/{x["games"]}', f'conf {x["mean_conf"]:.3f} succ {x["move_success"]:.3f} n={x["samples"]}',
          f'brier {x["brier"]} ece {x["ece"]} [{x["ece_ci_low"]},{x["ece_ci_high"]}] res {x["resolution"]}',
          f'inv {x["invalid"]}/{x["llm_calls"]} tmo {x["timed_out_calls"]} lat {x["mean_latency_ms"]} pert {x["perturbed"]} {x["wall_seconds"]}s', x["outcomes"])
