"""Area #3 W1 — active shot_director prompt residue gate.

7 exact substring literals MUST be absent from the latest active prompt
(grep substring match, not regex execution). Generic Korean particles
(를/을/의) 자체는 gate 대상 X — false positive 회피.

Scope: prompts/_base/shot_director/<latest>/system.md only.
Legacy archive prompts/_base/shot_director/[1-5].*/ 제외.
"""
from pathlib import Path

import pytest

from app.modules.prompt_loader import _version_sort_key


REPO_ROOT = Path(__file__).resolve().parents[2]
SHOT_DIRECTOR_PROMPT_BASE = REPO_ROOT / "prompts" / "_base" / "shot_director"

# 7 exact substring literals to ban (Codex iter 1 confirmation)
BANNED_LITERALS = (
    "X[를을]",
    "Y[의]",
    "Gaze-target close-up 패턴",
    "명시적 off-camera/off-screen phrase",
    "차단(blocking) 패턴",
    "Reaction-only 패턴",
    "(차단|막다|가리다|block|obstruct)",
)


def _latest_version_dir(base: Path) -> Path:
    """`prompts/_base/shot_director/` 아래 가장 최신 버전 디렉토리 반환.

    `_version_sort_key` 와 동일한 numeric-aware 정렬 (major segment int cast,
    secondary lexical) — `9.x` vs `10.x` 정렬 오류 회피.
    """
    candidates = [d for d in base.iterdir() if d.is_dir()]
    if not candidates:
        raise RuntimeError(f"No version directories under {base}")
    candidates.sort(key=lambda d: _version_sort_key(d.name), reverse=True)
    return candidates[0]


def _read_active_system_md() -> tuple[Path, str]:
    latest = _latest_version_dir(SHOT_DIRECTOR_PROMPT_BASE)
    system_md = latest / "system.md"
    return system_md, system_md.read_text(encoding="utf-8")


@pytest.mark.parametrize("literal", BANNED_LITERALS)
def test_active_prompt_no_banned_literal(literal: str):
    """7 banned literals MUST be absent from active shot_director prompt."""
    path, content = _read_active_system_md()
    assert literal not in content, (
        f"Banned literal {literal!r} found in active prompt {path}. "
        f"Area #3 W1 prompt v6 rewrite required."
    )


def test_active_prompt_is_v6_or_later():
    """Active shot_director prompt must be v6 or later (no Korean grammar bundle)."""
    latest = _latest_version_dir(SHOT_DIRECTOR_PROMPT_BASE)
    major = int(latest.name.split(".")[0])
    assert major >= 6, (
        f"Active shot_director prompt {latest.name} < v6. "
        f"Area #3 W1 requires prompt v6+."
    )


def test_active_prompt_contains_bp_guard():
    """Active shot_director prompt MUST contain BP guard (W0 §2.3 false-positive guard).

    Without this guard, post-W2 (mutation removal) the LLM may incorrectly apply
    'Gaze target close-up' rule to body-part possession cases, wrongly excluding
    characters in two-shot composition.
    """
    path, content = _read_active_system_md()
    # Stable phrase markers — must survive minor wording revisions
    assert "Body-part / posture guard" in content, (
        f"BP guard label missing from active prompt {path}. "
        f"W0 §2.3 prescribes false-positive guard for body-part possession. "
        f"Required before W2 mutation removal."
    )
    assert "false-positive guard" in content, (
        f"'false-positive guard' marker missing from active prompt {path}. "
        f"Used to distinguish BP guard from exclusion-trigger rules."
    )
