"""W20F10 O — coordinator fallback 정책: zoom_in_detail 일 때 location_history fallback 차단.

Scene 38 (S25_Shot3) 가 cap exceeded 로 dep_scene PNG 부재 → coordinator 가
location_history bytes 로 silent fallback → ref_usage='zoom_in_detail' 와
bytes provenance mismatch → callee (scene_reference_service.py:994 Layer 3)
RefContractError. cap exceeded 본질을 가렸다.

본 정책은 단순:
  - `ref_usage_for_this_shot == "zoom_in_detail"` AND dep_scene bytes 없으면
    `best_prev_bytes=None`, `bytes_source_kind="none"` 유지. location_history
    fallback 절대 진입 X. optional warning 로그 허용.

두 fallback block (`build_scene_attached_refs` + `_generate_scene_in_loop`)
모두 동일 정책. 본 테스트는 두 block 모두 동일하게 패치됐는지 ast 정적 검증.
runtime 호출 경로는 무거운 fixture 가 필요해 별도 wave 에서 다룸.
"""
from __future__ import annotations

import ast
from pathlib import Path


_TARGET = (
    Path(__file__).resolve().parents[2]
    / "app" / "services" / "scene_generation_coordinator.py"
)


def _all_function_defs(tree: ast.AST) -> dict[str, ast.FunctionDef]:
    funcs: dict[str, ast.FunctionDef] = {}
    for node in ast.walk(tree):
        if isinstance(node, ast.FunctionDef):
            funcs.setdefault(node.name, node)
    return funcs


def _function_body_text(func: ast.FunctionDef) -> str:
    source = _TARGET.read_text(encoding="utf-8")
    start = func.lineno
    end = getattr(func, "end_lineno", None) or (start + 200)
    lines = source.splitlines()
    return "\n".join(lines[start - 1: end])


def _assert_policy_in_function(func_name: str) -> None:
    tree = ast.parse(_TARGET.read_text(encoding="utf-8"))
    funcs = _all_function_defs(tree)
    assert func_name in funcs, f"function {func_name} not found"
    body = _function_body_text(funcs[func_name])
    assert (
        '_ref_usage_for_policy != "zoom_in_detail"' in body
    ), (
        f"{func_name}: zoom_in_detail 가드 누락 — fallback 조건절에서 "
        '`_ref_usage_for_policy != "zoom_in_detail"` 필요 (W20F10 O policy).'
    )
    assert (
        'bytes_source_kind = "location_history"' in body
    ), f"{func_name}: location_history fallback 본문 자체가 유지돼야 (다른 ref_usage 정상 경로)."
    assert (
        'dep_detail_map' in body and 'ref_usage' in body
    ), (
        f"{func_name}: dep_detail_map / ref_usage lookup 누락 — string 의미 추론 "
        "대신 dep_detail_map[key].ref_usage SOT 사용 의무."
    )


def test_build_scene_attached_refs_has_zoom_policy():
    _assert_policy_in_function("build_scene_attached_refs")


def test_generate_scene_in_loop_has_zoom_policy():
    _assert_policy_in_function("_generate_scene_in_loop")
