"""Carry-A099 — VWR system.md director_notes prose abstraction integrated test.

6 Gate verify (closed-world exact phrase membership only):
- Gate 1 (G4): R1-R9 9 strict residue absence (exact full-phrase) in v8 system.md.
- Gate 2 (G3): rules_schema.json sha256 byte-identical from v7.
- Gate 3 (G5): canonical process wording presence + enumerated output taxonomy absence.
- Gate 4 (G6): STEP_MANIFEST['visual_world_rules']['schema_version'] == 1 preserve.
- Gate 5 (optional, G7): director_steps.py:122-128 fallback chain source preservation canary.
- Gate 6 (G1): historical v8 closure anchor proof via literal VWR_V8_DIR pin + schema-specific VWR_V8_DIR/rules_schema.json existence (Carry-A100 W1 historical pin refactor 정합).

NO VLM + no live LLM + no regex semantic + no standalone token global ban.
"""

import hashlib
import re
from pathlib import Path

from app.core.step_manifest import STEP_MANIFEST


REPO_ROOT = Path(__file__).resolve().parents[3]
VWR_V7_DIR = REPO_ROOT / "prompts/_base/visual_world_rules/7.202605181540"
VWR_V8_DIR = REPO_ROOT / "prompts/_base/visual_world_rules/8.202605191102"


R1_R9_STRICT = [
    "회상/F.B 장면의 인물·소품·혈흔 등은 회상하는 인물의 기억 이미지이며, 회상 종료 후 현재 씬 공간에는 물리적으로 존재하지 않는다.",
    "특정 인물에게만 보이는 환각/현시 대상은 다른 인물이 등장하는 씬에서는 화면에서 제거한다.",
    "CCTV·모니터·창문 너머 등 화면 매개로 보이는 인물은 그 매개 표면 안쪽 평면 이미지로만 그리고, 매개 밖 공간에는 두지 않는다.",
    "교차편집/몽타주로 다른 장소가 보일 때 두 장소의 인물을 한 프레임에 합치지 않는다.",
    "안개·어둠 등 시야 차단 장치는 그 안의 대상을 명확히 묘사하지 말고 차단 그대로 둔다.",
    '"인물A 가 보는 인물B 의 시신은 인물A 의 환각으로 우선 판단한다."',
    '"수사관과 형사가 장소X 에 도착했을 때 시신이 사라진 상태라면..."',
    '"특정 씬 번호의 시신은 회상 이미지이다."',
    '"인물C 의 배가 안개로 들어가는 장면은 다른 세계 이동이 아니다."',
]


def _v8_dir() -> Path:
    return VWR_V8_DIR


def test_gate_1_r1_r9_residue_absent_in_v8_system_md():
    """G4: 9 strict R-id full-phrase membership hit 0 in v8 system.md."""
    v8 = _v8_dir()
    sys_md = (v8 / "system.md").read_text(encoding="utf-8")
    for idx, residue in enumerate(R1_R9_STRICT, start=1):
        assert residue not in sys_md, f"R{idx} residue present in v8 system.md"


def test_gate_2_rules_schema_sha256_byte_identical_from_v7():
    """G3: rules_schema.json sha256 byte-identical from v7."""
    v8 = _v8_dir()
    v7_bytes = (VWR_V7_DIR / "rules_schema.json").read_bytes()
    v8_bytes = (v8 / "rules_schema.json").read_bytes()
    v7_sha = hashlib.sha256(v7_bytes).hexdigest()
    v8_sha = hashlib.sha256(v8_bytes).hexdigest()
    assert v7_sha == v8_sha, f"rules_schema sha mismatch v7={v7_sha} v8={v8_sha}"


def test_gate_3_canonical_process_wording_presence_and_no_enum_taxonomy():
    """G5: canonical process wording present + enumerated output taxonomy absent."""
    v8 = _v8_dir()
    sys_md = (v8 / "system.md").read_text(encoding="utf-8")
    en_pres = "principle must be scenario-agnostic" in sys_md
    kr_pres = "원칙은 시나리오에 무관하며" in sys_md
    assert en_pres or kr_pres, "canonical process wording (EN or KR) absent"
    taxonomy_pattern = re.compile(r"category\s*:\s*\[")
    assert not taxonomy_pattern.search(sys_md), "enumerated output taxonomy detected"


def test_gate_4_step_manifest_schema_version_preserve():
    """G6: STEP_MANIFEST['visual_world_rules']['schema_version'] == 1 preserve."""
    assert STEP_MANIFEST["visual_world_rules"]["schema_version"] == 1


def test_gate_5_fallback_chain_source_preservation():
    """G7 (optional): director_steps.py:122-128 fallback chain source preservation canary.

    No file edit verify — line range 안 'possession', 'projection', 'ghost' literal presence preserve.
    """
    director_steps = REPO_ROOT / "backend/app/core/steps/director_steps.py"
    src = director_steps.read_text(encoding="utf-8")
    lines = src.splitlines()
    fallback_block = "\n".join(lines[120:128])
    for rule_type in ("possession", "projection", "ghost"):
        assert rule_type in fallback_block, f"fallback chain rule_type '{rule_type}' missing"


def test_gate_6_v8_historical_closure_anchor_proof():
    """G1: historical v8 closure anchor proof via literal VWR_V8_DIR pin + schema-specific VWR_V8_DIR/rules_schema.json existence.

    Carry-A100 W1 historical pin refactor — active resolution dependency 폐기.
    """
    assert _v8_dir() == VWR_V8_DIR
    schema_file = VWR_V8_DIR / "rules_schema.json"
    assert schema_file.is_file(), f"schema-specific file existence FAIL: {schema_file}"
    assert "/visual_world_rules/8.202605191102" in str(schema_file), f"schema-specific path FAIL: {schema_file}"
