"""세계관(visual_world_rules) → 프롬프트 블록 조립 — 공용 SOT.

2026-07-25 사용자 지적("맵도 콘티도 샷 이미지도 한국적이지 않다") 실측:
야외 장소 경로만 세계관이 **한 글자도 도달하지 않았다**.
  - outdoor_place_spec_step: ``rules_text``/``text`` 키를 읽는데 CP 에는
    그런 키가 없다(실제 키=region/era/rules/t2i_context) → 항상 "".
  - outdoor_place_canon_step: ``world_facts_block = ""`` 하드코딩.
    (주석은 '제작자 정정 원문 재주입 금지'가 근거인데, 그건 정정 채널
    이야기이고 세계관 자체는 애초에 주입된 적이 없다 — 별개 결손.)
반면 entity_steps/beat_shot_steps 는 region·era·t2i_context 를 정상
주입한다. 그 관례를 모듈로 승격해 야외 경로에도 같은 사실을 흘린다.

코드는 조립만 한다 — 내용은 전부 CP 데이터(시나리오 의존 하드코딩 0).
"""
from __future__ import annotations

from typing import Any, Dict, Optional

# 이미지 프롬프트에 실을 규칙 종류 — 장소/공간의 물성에 관여하는 것만.
# body_deformation·projection 등 인물/현상 규칙은 장소 T2I 에 넣으면
# 무관 장소까지 오염된다(캐논 정정 원문 오염 실측과 같은 계열).
PLACE_RULE_TYPES = ("time_period", "technology", "architecture",
                    "environment", "culture")


def _vwr_data(cp: Optional[Dict[str, Any]]) -> Dict[str, Any]:
    return (cp or {}).get("data", {}) or {}


def build_world_facts_block(cp: Optional[Dict[str, Any]]) -> str:
    """장소 이미지(캐논 사진/맵) 프롬프트용 세계 사실 블록.

    region·era 는 그 지역·시대의 **실제 건축·시설 관행**을 부르는 앵커다
    (이미지 모델이 "대한민국 2020년대"를 알면 정류장·표지·노면 표기가
    그 나라 것이 된다). 장소 물성에 관여하는 rule 의 visual_guideline
    만 함께 싣고, 인물/현상 규칙은 제외한다. CP 부재/빈 값=빈 문자열
    (호출부 byte-identical).
    """
    d = _vwr_data(cp)
    region = str(d.get("region") or "").strip()
    era = str(d.get("era") or "").strip()
    lines = []
    if region:
        lines.append(f"- Region (real-world reference): {region}")
    if era:
        lines.append(f"- Era: {era}")
    for r in d.get("rules") or []:
        if not isinstance(r, dict):
            continue
        if r.get("rule_type") not in PLACE_RULE_TYPES:
            continue
        guide = str(r.get("visual_guideline") or "").strip()
        if guide:
            lines.append(f"- {guide}")
    if not lines:
        return ""
    return "\n".join(lines)


def build_world_rules_text(cp: Optional[Dict[str, Any]]) -> str:
    """장소 스펙 저작(LLM)용 세계 물리 규칙 텍스트.

    저작 LLM 은 이미지 모델과 달리 규칙 전체를 관련성 판단에 쓸 수
    있으므로 rule_type 필터 없이 전부 싣는다(기존 spec 프롬프트의
    '세계 물리 규칙(참고)' 슬롯 계약 그대로).
    """
    d = _vwr_data(cp)
    parts = []
    region = str(d.get("region") or "").strip()
    era = str(d.get("era") or "").strip()
    if region:
        parts.append(f"지역: {region}")
    if era:
        parts.append(f"시대: {era}")
    for r in d.get("rules") or []:
        if not isinstance(r, dict):
            continue
        desc = str(r.get("description") or "").strip()
        guide = str(r.get("visual_guideline") or "").strip()
        rtype = str(r.get("rule_type") or "").strip()
        if desc or guide:
            head = f"[{rtype}] " if rtype else ""
            parts.append(f"{head}{desc}".strip())
            if guide:
                parts.append(f"  시각 지침: {guide}")
    return "\n".join(parts)
