"""카드에서 **샷마다 똑같은 것**이 얼마나 되나 — 그것은 샷별로 보낼 이유가 없다."""
import json,re,sys
from collections import defaultdict
sys.path.insert(0,"/Users/manta/Documents/Projects/TheRoad-I1/scratchpad")
from _opik_env import opik_target
from tools.opik_prompt_audit.audit.fetch import fetch_spans
B,W,P=opik_target()
cards=[]
for x in sorted((s for s in fetch_spans(B,W,P,"2026-08-24T19:20:00","2026-12-31T00:00:00")
                 if "op:scene_detail" in (s.get("tags") or [])),key=lambda s:s["start_time"]):
    inp=x.get("input"); msgs=inp if isinstance(inp,list) else (inp or {}).get("messages") or []
    u="".join((m.get("content") or "") for m in msgs if m.get("role")=="user" and isinstance(m.get("content"),str))
    m2=re.search(r"\[RenderPromptCard v1\]\n(\{.*?\})\n",u,re.S)
    if m2:
        try: cards.append(json.loads(m2.group(1)))
        except Exception: pass
print(f"카드 {len(cards)}장\n")

def walk(node, path=""):
    """말단 값마다 (경로, 직렬화문자열) 산출."""
    if isinstance(node, dict):
        for k,v in node.items(): yield from walk(v, f"{path}.{k}")
    elif isinstance(node, list):
        yield path, json.dumps(node, ensure_ascii=False, sort_keys=True)
    else:
        yield path, json.dumps(node, ensure_ascii=False)

vals=defaultdict(set); size=defaultdict(int)
for c in cards:
    for p,v in walk(c):
        vals[p].add(v); size[p]=max(size[p], len(v))

static=[(p,size[p]) for p in vals if len(vals[p])==1]
var=[(p,size[p]) for p in vals if len(vals[p])>1]
S_=sum(s for _,s in static); V_=sum(s for _,s in var)
print(f"정적(모든 샷 동일) {len(static)}개 항목 · {S_:,}자")
print(f"가변             {len(var)}개 항목 · {V_:,}자")
print(f"→ 카드의 {100*S_/(S_+V_):.0f}% 가 샷마다 똑같다\n")
print("── 정적인 것 중 큰 것 ──")
for p,s in sorted(static,key=lambda kv:-kv[1])[:14]:
    print(f"{s:>7,}자  {p}")
