"""G3.2 round 4 MINOR 2 (Task 19.6): consumer propagation regression guard.

`owned_validation` 이 t2i_review / scene_still_normalizer / scene_checkpoint_loaders
를 통과해도 strip 안 되는지 회귀 가드.

- _normalize_scene_detail_result (scene_detail entry helper) deep copy 시 보존.
- 위 3 consumer 모듈 source 안에 명시적 `owned_validation` strip 코드가 없는지.
"""
from __future__ import annotations

import copy
import inspect
from typing import Any, Dict

from app.core.steps._owned_helpers import (
    OWNED_VALIDATOR_FULL,
    build_owned_sentinel,
)


def _make_t2i_variation_with_sentinel() -> Dict[str, Any]:
    t2i_prompt = "Photorealistic still — door from reference"
    sentinel = build_owned_sentinel(
        owned=["door", "window"],
        camera_direction="wide eye-level",
        t2i_prompt=t2i_prompt,  # round 5 BLOCKING 3
        is_close_framing=False,
        violations=[],
        owned_object_usage=[  # C2 v1: owned token 전부 absent echo
            {"owned_token": "door", "usage_kind": "absent", "source_phrase": ""},
            {"owned_token": "window", "usage_kind": "absent", "source_phrase": ""},
        ],
    )
    return {
        "variant_label": "var_1",
        "camera_effect": "wide eye-level",
        "t2i_prompt": t2i_prompt,
        "outfit_assignments": [],
        "source_facts": ["fact"],
        "visual_inferences": ["inf"],
        "creative_decisions": ["dec"],
        "confidence": "high",
        "owned_validation": sentinel,
    }


# ---------------------------------------------------------------------------
# _normalize_scene_detail_result (G3.1 entry helper) preservation
# ---------------------------------------------------------------------------


def test_normalize_scene_detail_result_preserves_owned_validation():
    """G3.1 normalize 가 owned_validation 안 strip 하는지."""
    from app.core.steps._evidence_helpers import _normalize_scene_detail_result

    var = _make_t2i_variation_with_sentinel()
    sentinel_before = copy.deepcopy(var["owned_validation"])
    scene_result = {
        "scene_index": 1, "_shot_index": 1,
        "t2i_variations": [var],
    }
    _normalize_scene_detail_result(scene_result, where="test")
    assert "owned_validation" in scene_result["t2i_variations"][0]
    assert scene_result["t2i_variations"][0]["owned_validation"] == sentinel_before


def test_normalize_scene_detail_result_deep_copy_round_trip_preserves():
    """deep copy round-trip 시에도 owned_validation 보존 + 동등."""
    from app.core.steps._evidence_helpers import _normalize_scene_detail_result

    var = _make_t2i_variation_with_sentinel()
    scene_result = {
        "scene_index": 1, "_shot_index": 1,
        "t2i_variations": [var],
    }
    _normalize_scene_detail_result(scene_result, where="t1")
    cloned = copy.deepcopy(scene_result)
    _normalize_scene_detail_result(cloned, where="t2")
    assert cloned["t2i_variations"][0]["owned_validation"] == \
        scene_result["t2i_variations"][0]["owned_validation"]


# ---------------------------------------------------------------------------
# t2i_review / scene_still_normalizer / scene_checkpoint_loaders source guards
# ---------------------------------------------------------------------------


_FORBIDDEN = (
    'pop("owned_validation"',
    "pop('owned_validation'",
    'del var["owned_validation"]',
    "del var['owned_validation']",
    'del v["owned_validation"]',
    "del v['owned_validation']",
    'del item["owned_validation"]',
    "del item['owned_validation']",
)


def _assert_no_strip(module) -> None:
    src = inspect.getsource(module)
    for pat in _FORBIDDEN:
        assert pat not in src, (
            f"{module.__name__} 가 owned_validation 을 명시적으로 strip 하면 안 됨: {pat}"
        )


def test_t2i_review_preserves_owned_validation_source():
    """t2i_review.py source 안에 owned_validation strip 코드 없음."""
    from app.modules.pipeline import t2i_review
    _assert_no_strip(t2i_review)


def test_scene_still_normalizer_preserves_owned_validation_source():
    """scene_still_normalizer.py source 안에 owned_validation strip 코드 없음."""
    from app.services.checkpoint_sync import scene_still_normalizer
    _assert_no_strip(scene_still_normalizer)


def test_scene_checkpoint_loaders_preserves_owned_validation_source():
    """scene_checkpoint_loaders.py source 안에 owned_validation strip 코드 없음."""
    from app.services import scene_checkpoint_loaders
    _assert_no_strip(scene_checkpoint_loaders)
