"""Area #2 W7 — shot_visibility Path 1 (gaze_direction_kind + gaze_target_id) read.

Area #3 W3 update: Path 1/2 split 후 Path 1 region anchor 가 함수 분리 후
``detect_offscreen_drift_structured`` 함수 본체로 이동. Path 2 (Korean lexicon /
camera_direction offscreen proximity diagnostic) = ``detect_offscreen_drift_
proximity_diagnostic`` 함수, 본 test scope 외 (production behavior 무변경 verify).
"""
from __future__ import annotations

import ast


def _read_function_source(module_path: str, func_name: str) -> str:
    """모듈 파일 안 특정 top-level 함수의 source text 추출."""
    src = open(module_path).read()
    tree = ast.parse(src)
    for node in tree.body:
        if isinstance(node, ast.FunctionDef) and node.name == func_name:
            start = node.lineno - 1
            end = node.end_lineno  # ast inclusive end
            return "\n".join(src.splitlines()[start:end])
    raise AssertionError(
        f"function {func_name!r} not found in {module_path}"
    )


def test_path1_reads_gaze_direction_kind():
    """Path 1 — legacy `ca.get("gaze_target")` direction read 폐기 + v13 structured field 도입."""
    import app.modules.pipeline.shot_visibility as sv
    source = open(sv.__file__).read()
    # 신 read: gaze_direction_kind (Path 1 안 도입)
    assert "gaze_direction_kind" in source, (
        "shot_visibility.py 가 gaze_direction_kind structured read 안 함 — W7 미완료"
    )
    # dispatch helper 사용 — Q7 closure structural validation only
    assert "resolve_visible_character_target" in source, (
        "shot_visibility.py 가 resolve_visible_character_target helper import 안 함 — Q7 dispatch 미적용"
    )
    # Path 1 region = detect_offscreen_drift_structured 함수 본체.
    # producer-side `detect_gaze_pattern_exclusions` 와 분리.
    path1_region = _read_function_source(
        sv.__file__, "detect_offscreen_drift_structured",
    )
    assert 'ca.get("gaze_target"' not in path1_region, (
        "Path 1 region 안 legacy `ca.get(\"gaze_target\")` 잔존 — W7 미완료"
    )
    assert "ca.get('gaze_target'" not in path1_region, (
        "Path 1 region 안 legacy `ca.get('gaze_target')` 잔존 — W7 미완료"
    )


def test_path1_uses_helper_dispatch_no_name_matching():
    """Path 1 — helper dispatch only (canonical name matching 금지, Q7 closure 정합).

    Path 1 안 name matching / canonical name lookup 금지 — gaze_target_id short_id
    (C##) 만 사용, helper 가 structural validation 수행. character/object 재판정
    금지 (Gate 1).
    """
    import app.modules.pipeline.shot_visibility as sv
    source = open(sv.__file__).read()
    # gaze_direction module 에서 helper import
    assert "from app.core.gaze_direction import" in source, (
        "shot_visibility.py 가 app.core.gaze_direction import 안 함"
    )
    # Path 1 region = detect_offscreen_drift_structured 함수 본체.
    path1_region = _read_function_source(
        sv.__file__, "detect_offscreen_drift_structured",
    )
    assert "looks_at_character" in path1_region, (
        "Path 1 region 안 'looks_at_character' kind 검사 부재 — kind branching 의무"
    )
    # Gate 4: gaze_direction_kind 는 v13 schema required, silent default 금지
    assert "ca.get('gaze_direction_kind'" not in path1_region
    assert 'ca.get("gaze_direction_kind"' not in path1_region


def test_path2_korean_lexicon_unchanged():
    """Path 2 (Korean NL proximity diagnostic) 핵심 logic 유지 verify —
    Area #3 boundary 정합.

    W3 split 이후 Path 2 region = ``detect_offscreen_drift_proximity_diagnostic``
    함수. Path 2 안 ``_PROXIMITY_PRE`` / ``_PROXIMITY_POST`` window-based name
    matching 유지 — Area #3 spec 안 drift detector 추후 정리. Path 2 production
    blocking 권한 제거 (caller logger.warning) 외 W3 안 내부 logic 변경 X.
    """
    import app.modules.pipeline.shot_visibility as sv
    source = open(sv.__file__).read()
    # Path 2 함수 존재
    path2_region = _read_function_source(
        sv.__file__, "detect_offscreen_drift_proximity_diagnostic",
    )
    # Path 2 핵심 logic: _PROXIMITY_PRE / _PROXIMITY_POST window + rfind / .name
    assert "_PROXIMITY_PRE" in source
    assert "_PROXIMITY_POST" in source
    assert "_PROXIMITY_PRE" in path2_region
    assert "_PROXIMITY_POST" in path2_region
    # Path 2 안 OFFSCREEN_RE finditer 유지
    assert "OFFSCREEN_RE" in path2_region
