"""Area #5 v1 — production + active prompt residue gate (spec §9, 7-항목 split).

Codex iter 2 I-1 pattern (Area #4 lesson 24) 의 strict form:
`hits=0; for ...; if rg ...; then hits=1; fi; done; test "$hits" -eq 0`

- Production residue gate (4): ref_contract_validator legacy identifier / coordinator
  validate_attached_refs kwarg / render_prompt_card closed-list / prompt_service phantom.
- Active prompt residue gate (3): scene_image v4 / t2i_review v5 / scene_detail v26.

phantom guard SOT 는 sidecar (structured) — code regex / prompt closed-list 0 hits 강제.
NO VLM. structured SOT only.
"""
from __future__ import annotations

import glob
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parents[3]


def _grep_count(pattern: str, rel_path: str) -> int:
    """plain-text substring count — file 또는 dir glob 지원.

    pure Python (no rg dependency). file path 면 단일 file 의 substring count,
    trailing `/` 면 그 dir 의 모든 file 합산 (재귀).
    """
    target = REPO_ROOT / rel_path
    paths: list[Path] = []
    if target.is_file():
        paths = [target]
    elif target.is_dir() or str(rel_path).endswith("/"):
        # 재귀 file scan
        paths = [p for p in target.rglob("*") if p.is_file()]
    else:
        raise RuntimeError(f"path not found: {target}")
    total = 0
    for p in paths:
        try:
            text = p.read_text(encoding="utf-8", errors="ignore")
        except (UnicodeDecodeError, PermissionError, OSError):
            continue
        if pattern in text:
            total += text.count(pattern)
    return total


# ──────────────────────────────────────────────────────────────────────
# Production residue gate (4 항목)
# ──────────────────────────────────────────────────────────────────────


def test_residue_gate_1_ref_contract_validator_legacy_identifiers_zero():
    """Item 1: ref_contract_validator.py — 13 legacy identifier 0 hits."""
    identifiers = [
        "_CHARACTER_TOKENS", "_BACKGROUND_TOKENS", "_OBJECT_TOKENS",
        "_FROM_THE_REFERENCE_RE", "_PLURAL_REFERENCE_IMAGES_RE",
        "_PHRASE_LOCAL_WINDOW", "_PHRASE_FALLBACK_WINDOW",
        "_GENERIC_VERB_TOKENS", "_GENERIC_NOUN_TOKENS",
        "_classify_window", "_is_plural_reference_images",
        "_has_generic_instruction_signal", "classify_from_the_reference",
    ]
    hits = 0
    for ident in identifiers:
        if _grep_count(ident, "backend/app/core/ref_contract_validator.py") > 0:
            hits = 1
            print(f"FOUND legacy identifier: {ident}")
    assert hits == 0, (
        "ref_contract_validator.py 에 W2 폐기 13 legacy identifier 잔존 — "
        "Area #5 W2 atomic delete 정합 깨짐"
    )


def test_residue_gate_2_scene_generation_coordinator_validator_kwarg():
    """Item 2: scene_generation_coordinator.py — validate_attached_refs call 모두
    reference_phrase_kinds= keyword 동반 (line-window scan, regex truncate 회피).
    """
    path = REPO_ROOT / "backend/app/services/scene_generation_coordinator.py"
    lines = path.read_text().splitlines()
    hits = 0
    i = 0
    while i < len(lines):
        if "validate_attached_refs(" in lines[i] and "def validate_attached_refs" not in lines[i]:
            block_end = min(len(lines), i + 12)
            block_text = "\n".join(lines[i:block_end])
            if "reference_phrase_kinds=" not in block_text:
                hits = 1
                print(f"MISSING reference_phrase_kinds= kwarg at line {i+1}: {lines[i].strip()}")
        i += 1
    assert hits == 0, (
        "scene_generation_coordinator.py 안 validate_attached_refs(...) 호출 중 "
        "reference_phrase_kinds= keyword 누락 site 존재 — W3 caller cascade 불완전"
    )


def test_residue_gate_3_render_prompt_card_closed_list_literals_zero():
    """Item 3: render_prompt_card.py — closed-list 6 literal 0 hits."""
    literals = [
        "the existing X",
        "use the X from the reference",
        "matching the reference camera",
        "the door from the reference",
        "preserving the same room perspective",
        "maintaining the reference's framing",
    ]
    hits = 0
    src = (REPO_ROOT / "backend/app/core/steps/render_prompt_card.py").read_text()
    for lit in literals:
        if lit in src:
            hits = 1
            print(f"FOUND closed-list literal in render_prompt_card.py: {lit!r}")
    assert hits == 0


def test_residue_gate_4_prompt_service_translate_phantom_closed_list_zero():
    """Item 4: prompt_service.py — phantom prohibition closed-list 3 literal 0 hits.

    `phantom guard` legacy wording 폐기 — sidecar SOT 로 의도 전달 (translate prompt
    system_prompt rewrite at Task 3.7).
    """
    literals = [
        "'from the reference'",
        "'from Reference image N'",
        "phantom guard",
    ]
    hits = 0
    src = (REPO_ROOT / "backend/app/services/prompt_service.py").read_text()
    for lit in literals:
        if lit in src:
            hits = 1
            print(f"FOUND closed-list literal in prompt_service.py: {lit!r}")
    assert hits == 0


# ──────────────────────────────────────────────────────────────────────
# Active prompt residue gate (3 항목)
# ──────────────────────────────────────────────────────────────────────


def _latest_prompt_dir(prefix_glob: str) -> str:
    """`prompts/_base/<module>/<major>.*/` glob 의 최신 dir relative path 반환."""
    dirs = sorted(glob.glob(str(REPO_ROOT / prefix_glob)))
    assert dirs, f"No prompt dir found matching {prefix_glob}"
    return dirs[-1].replace(str(REPO_ROOT) + "/", "")


def test_active_prompt_residue_scene_image_v4_no_phantom_phrase_prohibition():
    """Item 5: scene_image v4 active prompt — PHANTOM PHRASE PROHIBITION 0 hits.

    Area #5 W3 Task 3.4 rewrite — REFERENCE PRESERVATION principle-only.
    """
    latest = _latest_prompt_dir("prompts/_base/scene_image/4.*/")
    hits = _grep_count("PHANTOM PHRASE PROHIBITION", latest)
    assert hits == 0, (
        f"scene_image {latest} 안 'PHANTOM PHRASE PROHIBITION' 잔존 — "
        f"Area #5 W3 Task 3.4 wording cleanup 불완전"
    )


def test_active_prompt_residue_t2i_review_v5_no_close_framing_existing_ref():
    """Item 6: t2i_review v5 active prompt — close_framing_existing_ref 0 hits.

    Area #5 W3 Task 3.5 — issue type 4 section 전체 삭제 + enum 6→5.
    """
    latest = _latest_prompt_dir("prompts/_base/t2i_review/5.*/")
    hits = _grep_count("close_framing_existing_ref", latest)
    assert hits == 0, (
        f"t2i_review {latest} 안 'close_framing_existing_ref' 잔존 — "
        f"Area #5 W3 Task 3.5 issue type 4 section + enum 정리 불완전"
    )


def test_active_prompt_residue_scene_detail_v28_no_closed_phrase_examples():
    """Item 7: scene_detail v28 active prompt — closed-list phrase example 0 hits.

    Area #5 W1 producer schema v26 + prompt system.md Background Binding block
    rewrite (forbidden literals removed). Area #7b W3 v27 canonical VWR SOT
    reference clause cascade. Carry-D7d-1 v28 camera_effect.description align
    with Area #7d fallback policy (system.md byte-identical from v27, so forbidden
    literals removal preserved; active prompt latest = v28 fresh canary scope).
    """
    latest = _latest_prompt_dir("prompts/_base/scene_detail/28.*/")
    forbidden = ["from the reference", "the existing X", "shown in image N"]
    hits = 0
    for lit in forbidden:
        if _grep_count(lit, latest) > 0:
            hits = 1
            print(f"FOUND scene_detail v28 forbidden literal: {lit!r}")
    assert hits == 0
