"""참조 A/B — **순서를 가린** 사람 비교 화면. ★판을 차릴 뿐 판정하지 않는다.

대상마다 네 장을 **섞은 차례로** 놓는다. 어느 것이 참조를 넣은 것인지 화면에
안 적는다 — 알고 보면 판이 기운다.

    ★어느 쪽이 나은가는 **사람만** 정한다. VLM 점수·critique·다수결을
     근거로 안 쓴다.

정답표는 **따로** 낸다(`--key`). 사람이 고르고 **난 뒤에** 연다.

    python tools/grounding_audit/ref_ab_review.py <ab.json> <out.html>
    python tools/grounding_audit/ref_ab_review.py <ab.json> --key
"""
from __future__ import annotations

import html
import json
import sys
from collections import defaultdict
from pathlib import Path
from typing import Any, Dict


def _e(x: Any) -> str:
    return html.escape(str(x if x is not None else ""))


def render(doc: Dict[str, Any]) -> str:
    by: Dict[str, list] = defaultdict(list)
    for r in doc.get("rows") or ():
        if r.get("path"):
            by[str(r["subject_id"])].append(r)

    cards = []
    for sid in sorted(by):
        rows = sorted(by[sid], key=lambda x: x.get("slot") or 0)
        first = rows[0]
        cells = "".join(f"""
<figure class=shot>
  <img loading=lazy src="/{_e(r['path'])}" alt="{_e(r.get('slot'))}">
  <figcaption>{_e(r.get('slot'))}</figcaption>
</figure>""" for r in rows)
        cards.append(f"""
<article class=row>
  <header>
    <span class=own>{_e(first.get('owner_type'))}</span>
    <b>{_e(first.get('surface_form'))}</b>
    <span class=id>{_e(sid)}</span>
  </header>
  <div class=body>
    <section class=ref>
      <h4>고른 참조</h4>
      <img class=refimg loading=lazy src="/{_e(first['reference_path'])}">
      <h4>같은 프롬프트 (모델이 적은 겉모습)</h4>
      <p class=prompt>{_e(first.get('prompt'))}</p>
    </section>
    <section class=arms>
      <h4>구운 것 {len(rows)}장 — <span class=hint>차례는 섞여 있습니다</span></h4>
      <div class=shots>{cells}</div>
    </section>
  </div>
</article>""")

    return f"""<meta charset="utf-8">
<title>참조 A/B — 사람 비교</title>
<style>
 body{{font:14px/1.65 system-ui,-apple-system,sans-serif;margin:0;
   background:#f6f6f7;color:#1a1a1a}}
 .wrap{{max-width:1240px;margin:0 auto;padding:24px}}
 h1{{font-size:21px;margin:0 0 4px}}
 .note{{background:#fff8e1;border:1px solid #f0d98c;padding:12px 14px;
   border-radius:8px;margin:14px 0;font-size:13px}}
 .row{{background:#fff;border:1px solid #e3e3e6;border-radius:10px;
   margin:16px 0;overflow:hidden}}
 header{{display:flex;gap:10px;align-items:center;flex-wrap:wrap;
   padding:10px 14px;background:#fafafa;border-bottom:1px solid #eee}}
 .own{{font-size:11px;background:#eceff1;padding:2px 8px;border-radius:99px}}
 .id{{font-family:ui-monospace,monospace;font-size:11px;color:#777}}
 .body{{display:grid;grid-template-columns:300px 1fr;gap:0}}
 section{{padding:10px 14px;border-right:1px solid #f2f2f2}}
 h4{{margin:6px 0 4px;font-size:12px;color:#666;font-weight:600}}
 .refimg{{width:100%;border-radius:8px;background:#eee}}
 .prompt{{margin:0;font-size:12px;color:#333;background:#fafafa;padding:8px;
   border-radius:6px;white-space:pre-wrap}}
 .shots{{display:flex;gap:10px;flex-wrap:wrap}}
 .shot{{margin:0;width:230px}}
 .shot img{{width:100%;border-radius:8px;background:#eee;display:block}}
 figcaption{{text-align:center;font-size:12px;color:#666;padding:4px}}
 .hint{{color:#888;font-size:11px;font-weight:400}}
</style>
<div class=wrap>
<h1>참조 A/B — 사람 비교</h1>
<div class=note>
 대상마다 <b>같은 프롬프트</b>로 구운 {doc.get('repeats', 2) * 2}장이 있습니다.
 절반은 <b>참조를 넣고</b>, 절반은 <b>넣지 않고</b> 구운 것이며
 <b>차례는 섞여 있습니다</b> — 어느 쪽인지 화면에 안 적습니다.<br>
 <b>★어느 쪽이 나은지는 사람이 정합니다.</b> VLM 에게 좋고 나쁨을 묻지
 않았습니다.<br>
 <span class=hint>우리가 쓰는 이미지 API 에는 seed 가 없어 같은 그림을
 재현할 수 없습니다. 그래서 arm 당 여러 장을 굽습니다.</span>
</div>
{''.join(cards)}
</div>"""


def main() -> int:
    if len(sys.argv) < 3:
        print(__doc__)
        return 2
    doc = json.loads(Path(sys.argv[1]).read_text(encoding="utf-8"))
    if sys.argv[2] == "--key":
        print("■ 정답표 — ★사람이 고른 **뒤에** 본다")
        by: Dict[str, list] = defaultdict(list)
        for r in doc.get("rows") or ():
            if r.get("path"):
                by[str(r["subject_id"])].append(r)
        for sid in sorted(by):
            rows = sorted(by[sid], key=lambda x: x.get("slot") or 0)
            print(f"  {sid} {rows[0].get('surface_form')}")
            for r in rows:
                print(f"     자리 {r['slot']} = "
                      f"{'참조 넣음' if r['arm'] == 'with_reference' else '참조 없음'}"
                      f"  ({r['path'].split('/')[-1]})")
        return 0
    out = Path(sys.argv[2])
    out.write_text(render(doc), encoding="utf-8")
    print(f"■ 적었다: {out}")
    print("  ★차례를 가렸다. 정답표는 `--key` 로 따로 본다.")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
