#!/usr/bin/env python3
"""scene_detail 이 실제로 무엇을 보냈는지 뜯어본다 — Opik span 의 input 전문."""
import sys
from collections import Counter

sys.path.insert(0, "/Users/manta/Documents/Projects/TheRoad-I1/scratchpad")
from _opik_env import opik_target  # ★cwd 를 backend 로 고정 + 미로드 시 중단
from tools.opik_prompt_audit.audit.fetch import fetch_spans
from app.core.config import settings

BASE, WS, PROJ = opik_target()


spans = fetch_spans(BASE, WS, PROJ, "2026-08-24T13:00:00", "2026-08-24T16:10:00")


def msgs_of(sp):
    inp = sp.get("input")
    if isinstance(inp, dict):
        return inp.get("messages") or []
    if isinstance(inp, list):
        return inp
    return []


def role_text(sp, role):
    out = []
    for m in msgs_of(sp):
        if m.get("role") != role:
            continue
        c = m.get("content")
        if isinstance(c, str):
            out.append(c)
        elif isinstance(c, list):
            for part in c:
                if isinstance(part, dict) and part.get("type") == "text":
                    out.append(part.get("text") or "")
    return "\n".join(out)


target = [s for s in spans
          if any(str(t) == "step:scene_detail" for t in (s.get("tags") or []))]
print(f"scene_detail span: {len(target)}건\n")
if not target:
    print("태그로 못 찾음 — 이름으로 재시도")
    target = [s for s in spans if "scene_detail" in str(s.get("name", ""))]
    print(f"  이름 매치: {len(target)}건")

sizes = []
for sp in target:
    sysx, usr = role_text(sp, "system"), role_text(sp, "user")
    sizes.append((len(sysx), len(usr), sp))
sizes.sort(key=lambda x: -(x[0] + x[1]))

print(f"{'sys':>8} {'usr':>8} {'합':>8}  모델")
for s, u, sp in sizes:
    print(f"{s:>8,} {u:>8,} {s+u:>8,}  {sp.get('model')}")

if not sizes:
    raise SystemExit("대상 없음")

# ── 가장 큰 호출의 system 을 구획으로 쪼갠다 ──
_, _, big = sizes[0]
sysx = role_text(big, "system")
print(f"\n=== 가장 큰 호출의 system ({len(sysx):,}자) ===")

# 줄 단위로 「블록」을 나눈다: 빈 줄 2개 이상 = 구획
import re
blocks = re.split(r"\n\s*\n", sysx)
blocks = [b for b in blocks if b.strip()]
print(f"문단 {len(blocks)}개\n")
ranked = sorted(enumerate(blocks), key=lambda x: -len(x[1]))
for i, b in ranked[:18]:
    head = b.strip().split("\n", 1)[0][:78]
    print(f"  {len(b):>7,}자  #{i:<3} {head}")

# ── 호출 사이에 똑같은 문단이 몇 개인가 (정적 비율 실측) ──
print("\n=== 호출 간 공통 문단 (★모델별로 나눠 잰다) ===")
# ★한 덩어리로 교집합을 내면 안 된다 — 성격이 다른 두 호출(pro 본 호출 /
#   flash 보조)이 섞여 교집합이 0 이 되고, 「정적 비율 0」이라는 거짓 결론이
#   나온다. 실제로 감사 도구가 이 스텝을 0.00 으로 쟀다.
groups = {}
for s, u, sp in sizes:
    groups.setdefault(sp.get("model"), []).append(sp)

for model, sps in groups.items():
    print(f"\n── {model} · {len(sps)}건 ──")
    for role in ("system", "user"):
        per_call = [set(b.strip() for b in
                        re.split(r"\n\s*\n", role_text(sp, role)) if b.strip())
                    for sp in sps]
        if len(per_call) < 2:
            print(f"  {role}: 호출 1건 — 비교 불가")
            continue
        common = set.intersection(*per_call)
        common_chars = sum(len(b) for b in common)
        one = len(role_text(sps[0], role))
        pct = (common_chars / one * 100) if one else 0
        waste = common_chars * (len(sps) - 1)
        print(f"  {role}: 공통 문단 {len(common)}개 · {common_chars:,}자 "
              f"= 한 호출의 {pct:.1f}% · 재전송 {waste:,}자")
