import json, glob, os, re, sys, collections, psycopg
S=os.path.dirname(os.path.abspath(__file__))
conn=psycopg.connect(host=os.environ["POSTGRES_HOST"],user="quber",password=os.environ["POSTGRES_PASSWORD"],dbname="quber_rag")
titles={r[0]:r[1] for r in conn.execute("select doc_key, title from ade_playground.documents").fetchall()}
def norm(s): return re.sub(r"[\s$,%]|million|thousand","",(s or "").lower()).replace("—","-").replace("–","-").replace("(","-").replace(")","")
def cell_text(doc_id, ref):
    r=conn.execute("select cell_text from ade_playground.groundings where document_id=%s and ref_id=%s",(doc_id,ref)).fetchone(); return r[0] if r else None
for mode in ("B","A"):
    files=sorted(glob.glob(f"{S}/rerun_*.pipe{mode}.json"))
    if not files: continue
    G=collections.Counter(); base_chars=new_chars=0; picks=collections.Counter(); lost=[]; gained=[]; diffs=[]; ver_b=ver_n=0; nb=nn=0; res=collections.Counter(); hosted_same=0; hosted_scalar=0
    print(f"\n================ MODE {mode} ({'rows via resolver' if mode=='A' else 'whole picked tables'}) ================")
    print(f"{'document':28s} {'base->new scalar':17s} {'same':>4s} {'diff':>4s} {'lost':>4s} {'gain':>4s} {'err':>3s} | ctx tok base->new | cell-verified base/new")
    for f in files:
        d=json.load(open(f)); doc_id=d["doc_id"]; t=titles[d["doc_key"]][:28]; c=collections.Counter(); bc=nc=0; vb=vn=0
        for r in d["rows"]:
            b=r["baseline"]; c[(b["shape"],r["shape"])]+=1; picks[r["picks"]]+=1
            bc+=sum(b["context_chars"]); nc+=sum(r["context_chars"])
            for x in r.get("resolved",[]): res["row" if x.get("row") is not None else ("whole" if x.get("whole") else "declined")]+=1
            if b["shape"]=="scalar" and r["shape"]=="scalar":
                if norm(b["payload"].get("value"))==norm(r["payload"].get("value")): c["same"]+=1
                else: c["diff"]+=1; diffs.append((t,r["index"],r["question"][:60],b["payload"].get("value"),r["payload"].get("value"),r["cited_ids"][:1]))
            if b["shape"]=="scalar" and r["shape"]!="scalar": lost.append((t,r["index"],r["question"][:70],b["payload"].get("value"),r["shape"],(r["payload"].get("reason") or r.get("error") or "")[:140],r["context_ids"][:3]))
            if b["shape"]!="scalar" and r["shape"]=="scalar": gained.append((t,r["index"],r["question"][:60],r["payload"].get("value"),r["cited_ids"][:1]))
            for rec,which in ((b,"b"),(r,"n")):
                if rec["shape"]=="scalar":
                    cid=rec["cited_ids"][0] if rec["cited_ids"] else None; ct=cell_text(doc_id,cid) if cid else None
                    ok= ct is not None and norm(ct)==norm(rec["payload"].get("value"))
                    if which=="b": vb+=ok
                    else: vn+=ok
        bs=sum(v for k,v in c.items() if isinstance(k,tuple) and k[0]=="scalar"); ns=sum(v for k,v in c.items() if isinstance(k,tuple) and k[1]=="scalar")
        err=sum(v for k,v in c.items() if isinstance(k,tuple) and k[1]=="error")
        print(f"{t:28s} {bs:>3d} -> {ns:<10d} {c['same']:>4d} {c['diff']:>4d} {c[('scalar','unanswerable')]+c[('scalar','error')]:>4d} {c[('unanswerable','scalar')]:>4d} {err:>3d} | {bc/len(d['rows'])/4:6.0f} -> {nc/len(d['rows'])/4:5.0f}  | {vb}/{bs} vs {vn}/{ns}")
        for k,v in c.items(): G[k]+=v
        base_chars+=bc; new_chars+=nc; ver_b+=vb; ver_n+=vn; nb+=bs; nn+=ns
    print(f"ALL: scalar {nb} -> {nn}; same {G['same']}, diff {G['diff']}, lost {len(lost)}, gained {len(gained)}; context chars {100*new_chars/base_chars:.0f}% of 10-chunk baseline; cell-verified {ver_b}/{nb} -> {ver_n}/{nn}")
    print(f"picks per question: {dict(sorted(picks.items()))}" + (f"; resolver: {dict(res)}" if mode=="A" else ""))
    print(f"\n-- LOST ({len(lost)}):")
    for x in lost: print(f"  {x[0][:20]} [{x[1]}] {x[2]!r} base={x[3]!r} -> {x[4]}: {x[5]!r}\n      ctx={x[6]}")
    print(f"\n-- DIFF ({len(diffs)}):")
    for x in diffs: print(f"  {x[0][:20]} [{x[1]}] {x[2]!r} base={x[3]!r} new={x[4]!r} cite={x[5]}")
    print(f"\n-- GAINED ({len(gained)}):")
    for x in gained: print(f"  {x[0][:20]} [{x[1]}] {x[2]!r} -> {x[3]!r} cite={x[4]}")
