#!/usr/bin/env python3
"""Codex 가 낸 historical cohort 수치를 **내가 직접** 확인한다.

★Codex 는 자주 틀린다 — 받되 file:line·실측으로 확인한다.
★그리고 이 표본은 **같은 `image_asset` 행의 `prompt_used` 와 `file_path`**
 를 쓴다. records.json 태그 조인은 안 쓴다 — force/rerun 뒤에는 프롬프트
 세대와 이미지 세대가 갈릴 수 있고 `is_primary` 만으로는 그 짝 불일치를
 못 막는다(Codex 지적, 수용).

확인할 것:
  ① exact asset-prompt 짝이 있는 primary 직접 스틸 = 548장인가
  ② 선언 분포 close 192 · insert 37 · medium 136 · wide 183 인가
  ③ 좁은 선언에서 KEY BG 없음 = close 15 · insert 2 인가
  ④ 파일 생존 548/548 인가
  ⑤ 팩 문안 세대 — v6 camera_frame 인가, `never copy its camera framing` 0건인가
"""
import pathlib
import re
import sys
from collections import Counter

sys.path.insert(0, "/Users/manta/Documents/Projects/TheRoad-I1/scratchpad")
from _opik_env import opik_target  # noqa: E402  (cwd 를 backend 로 고정)

opik_target()  # 설정 미로드면 여기서 선다

from sqlalchemy import create_engine, text  # noqa: E402

from app.core.config import settings  # noqa: E402

ROOT = pathlib.Path("/Users/manta/Documents/Projects/TheRoad-I1")

_DECL = [("extreme close-up", "extreme close-up"), ("insert", "insert"),
         ("close-up", "close"), ("medium close", "medium close-up"),
         ("medium wide", "medium wide"), ("medium", "medium"),
         ("extreme wide", "extreme wide"), ("wide", "wide")]


def norm(raw: str) -> str:
    low = raw.lower()
    for needle, scale in _DECL:
        if needle in low:
            return scale
    return "?"


SQL = """
SELECT a.id, a.episode_id, a.still_id, a.file_path, a.prompt_used,
       a.generation_model, a.created_at, a.prompt_type
FROM image_asset a
WHERE a.asset_type='scene'
  AND a.is_primary=1
  AND a.prompt_used IS NOT NULL AND a.prompt_used <> ''
  AND (a.is_intermediate IS NULL OR a.is_intermediate = false)
  AND a.source_image_id IS NULL
  AND a.parent_image_id IS NULL
"""

eng = create_engine(settings.database_url)
with eng.connect() as c:
    rows = c.execute(text(SQL)).fetchall()

print(f"① 후보 행 {len(rows)}  (asset_type=scene · primary · prompt_used 있음 "
      f"· 비중간 · source/parent 없음)")

scales, alive, bg_by_scale, packs, models, epis = Counter(), 0, {}, Counter(), Counter(), Counter()
keep_exact = never_copy = 0
for aid, epi, still, path, prompt, model, created, ptype in rows:
    m = re.search(r"^- FRAMING SCALE: (.+)$", prompt, re.M)
    if not m:
        scales["(선언 없음)"] += 1
        continue
    s = norm(m.group(1))
    scales[s] += 1
    has_bg = bool(re.search(r"^- KEY BACKGROUND ELEMENTS:", prompt, re.M))
    bg_by_scale.setdefault(s, Counter())[
        "있음" if has_bg else "없음"] += 1
    packs[ptype or "(없음)"] += 1
    models[model or "(없음)"] += 1
    epis[epi] += 1
    if "keep it EXACTLY: its camera, perspective" in prompt:
        keep_exact += 1
    if "never copy its camera framing" in prompt:
        never_copy += 1
    if (ROOT / path).exists() or pathlib.Path(path).exists():
        alive += 1

print(f"④ 파일 생존 {alive}/{len(rows)}")
print(f"\n② 선언 분포: {dict(sorted(scales.items()))}")
print("\n③ 스케일별 KEY BG 유무:")
for s in sorted(bg_by_scale):
    print(f"     {s:16} {dict(bg_by_scale[s])}")
print(f"\n⑤ 배경 계약 문구: keep-EXACTLY {keep_exact} · "
      f"never-copy {never_copy} · 나머지 {len(rows)-keep_exact-never_copy}")
print(f"\nprompt_type: {dict(packs)}")
print(f"모델: {dict(models)}")
print(f"에피소드 상위: {epis.most_common(4)}")
