#!/usr/bin/env python3
"""汇总 results.jsonl → report.md: per-slot variant 对比 + 推荐 + per-shot 可选性"""
import json, sys
from pathlib import Path
from collections import defaultdict

OUT = Path('/home/kai/shared/shenyuan-iframe-eval')
rows = []
for line in (OUT / 'results.jsonl').read_text().splitlines():
    try: rows.append(json.loads(line))
    except: pass

slots = defaultdict(dict)
for r in rows:
    if 'error' in r or 'verdict' not in r: continue
    slots[r['id'].rsplit('_v',1)[0]][r['variant']] = r

def fmt(r):
    if not r: return "—"
    v = r['verdict']
    return f"v{r['variant']}:{v.get('verdict','?')}/{v.get('score','?')}"

lines = ["# 《她从深渊回来》条件帧 90 variants 评估报告 (qwen-eye)", "",
         f"评估时间: {__import__('time').strftime('%Y-%m-%d %H:%M')} | 引擎: Qwen3.8-27B VL (q3, :8125)", ""]

# summary
tot = sum(len(v) for v in slots.values())
npass = sum(1 for r in rows if r.get('verdict',{}).get('verdict')=='pass')
nfail = sum(1 for r in rows if r.get('verdict',{}).get('verdict')=='fail')
nborder = sum(1 for r in rows if r.get('verdict',{}).get('verdict')=='borderline')
nerr = sum(1 for r in rows if 'error' in r or 'verdict' not in r)
lines += [f"## 总览", "", f"- 评估: {tot} frames (pass {npass} / borderline {nborder} / fail {nfail} / err {nerr})", ""]

lines += ["## Per-slot 明细", "", "| slot | v1 | v2 | v3 | 推荐 |", "|---|---|---|---|---|"]
recommend = {}
for slot in sorted(slots):
    vs = slots[slot]
    best = None; best_key = None
    for k in ['1','2','3']:
        r = vs.get(k)
        if not r: continue
        v = r['verdict']
        key = (v.get('score',0), v.get('verdict')=='pass')
        if best is None or key > best_key:
            best, best_key = r, key
    rec = f"v{best['variant']}" if best and best['verdict'].get('verdict') in ('pass','borderline') and best['verdict'].get('score',0)>=6 else "重生成"
    recommend[slot] = (rec, best['verdict'].get('score') if best else None, best['verdict'].get('verdict') if best else None)
    row = [fmt(vs.get(k)) for k in ['1','2','3']]
    lines.append(f"| {slot} | {row[0]} | {row[1]} | {row[2]} | **{rec}** |")

lines += ["", "## 推荐 summary", "", "| shot | frame | 推荐 | score | verdict | reasons |", "|---|---|---|---|---|---|"]
byshot = defaultdict(list)
for slot,(rec,score,verd) in recommend.items():
    shot, ft = slot.rsplit('_',1)
    byshot[shot].append((ft, rec, score, verd))
for shot in sorted(byshot):
    for ft, rec, score, verd in sorted(byshot[shot]):
        r = slots.get(f"{shot}_{ft}", {}).get(rec.lstrip('v') if rec.startswith('v') else '1')
        reason = r['verdict'].get('reasons','') if r else ''
        lines.append(f"| {shot} | {ft} | {rec} | {score} | {verd} | {reason} |")

# fail reasons detail
lines += ["", "## fail/borderline 详情", ""]
for slot in sorted(slots):
    for k in ['1','2','3']:
        r = slots[slot].get(k)
        if r and r['verdict'].get('verdict') in ('fail','borderline'):
            lines.append(f"- **{r['id']}** ({r['verdict']['verdict']}, {r['verdict'].get('score')}): {r['verdict'].get('reasons','')}")

(OUT/'report.md').write_text('\n'.join(lines))
print(f"report: {OUT/'report.md'}")
print(f"total {tot}: pass {npass} / borderline {nborder} / fail {nfail} / err {nerr}")
