#!/usr/bin/env python3
"""JUDGE do-zero dos candidatos de oclusão (spike_candidates.json do unified) -> luma_switches.json.
Frame da ATIVA (alegadamente tampada) + da ALT proposta -> VLM decide o dodge. READ-ONLY nos originais.
Uso: occlusion_judge.py"""
import json, os, re
from vlm import ask_images, par_map
import cache_manifest as cm
import judgelib as J

_PROMPT_PATH = os.path.join(os.path.dirname(__file__), "prompts/occlusion_judge_v1.md")
PROMPT = open(_PROMPT_PATH).read()
OUT = "luma_switches.json"

def main():
    # CACHE: spike_candidates content-hash; judgelib/vlib no mtime (frame_of vive lá — bugfix
    # de cam name deve invalidar este estágio).
    _sig = {"content": cm.content_signature(["spike_candidates.json"]),
            "mtime": cm.input_signature(["placements.json", _PROMPT_PATH,
                                          os.path.join(os.path.dirname(__file__), "judgelib.py"),
                                          os.path.join(os.path.dirname(__file__), "vlib.py")])}
    if cm.is_fresh(".", "occlusion_judge", __file__, _sig) and os.path.exists(OUT):
        print(f"[cache] occlusion_judge: script+input inalterados, pulando VLM — reusando {OUT}")
        return
    cands = json.load(open("spike_candidates.json"))
    def work(ic):
        i, c = ic
        mid = (c["f0"] + c["f1"]) // 2
        a = J.frame_of(c["from"], mid)
        b = J.frame_of(c["to"], mid)
        if not a or not b:
            print(f"  f{c['f0']}: sem frame, pula"); return None
        txt, _ = ask_images([a, b], PROMPT)
        m = re.search(r'\{.*\}', txt, re.S)
        try: v = json.loads(m.group(0)) if m else {}
        except Exception: v = {}
        keep = bool(v.get("keep"))
        tc = f"{c['f0']//108000:02d}:{(c['f0']//1800)%60:02d}:{(c['f0']//30)%60:02d}"
        print(f"  [{i+1}/{len(cands)}] {tc} cam{c['from']}->cam{c['to']} d{c['delta']} -> {'KEEP' if keep else 'drop'} ({str(v.get('why',''))[:60]})")
        if not keep: return None
        return {"f0": c["f0"], "f1": c["f1"], "angle": c["to"], "to_cam": c["to"],
                "cause": "occlusion", "tc": tc, "conf": 0.8}
    out = [r for r in par_map(work, list(enumerate(cands))) if r]
    json.dump(out, open(OUT, "w"), indent=1)
    cm.mark_done(".", "occlusion_judge", __file__, _sig)
    print(f"\nluma_switches.json: {len(out)}/{len(cands)} dodges confirmados")

if __name__ == "__main__":
    main()
