"""
Deep Adversarial Verification Probe by Challenger 2
Empirically tests:
1. Scene 10, Scene 06, Scene 05 shot resolutions under live data
2. Adversarial metadata injection with corrupted character_asset_ref across all characters
3. Anchor-title conflict resolution
4. Extreme edge cases: None, empty dict, missing files, corrupted strings
"""

import sys
from pathlib import Path
import pytest

PROJECT_ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(PROJECT_ROOT / "05_Production_Pipeline"))

import production_orchestrator as po


class TestDeepEmpiricalLiveSceneProbes:
    """Empirical verification of live scenes requested in challenge instructions."""

    def test_scene10_explicit_shots(self):
        """
        Confirm ep01_scene10_shot11 & shot12 strictly resolve to Thúy Kiều.
        Confirm ep01_scene10_shot04, 05, 13 strictly resolve to Kim Trọng.
        """
        shots = dict(po.get_shots_for_scene("ep01_scene10"))
        assert len(shots) > 0, "Scene 10 has no shots!"

        # Confirm ep01_scene10_shot11 & shot12 strictly resolve to Thúy Kiều
        for sid in ["ep01_scene10_shot11", "ep01_scene10_shot12"]:
            sdata = shots[sid]
            resolved, take = po.resolve_start_frame_v2(sid, sdata)
            assert resolved is not None, f"{sid} resolved to None"
            assert "thuy_kieu" in Path(resolved).name.lower(), f"{sid} did not resolve to Thúy Kiều: {resolved}"
            assert "kim_trong" not in Path(resolved).name.lower(), f"{sid} leaked Kim Trọng: {resolved}"

        # Confirm ep01_scene10_shot04, 05, 13 strictly resolve to Kim Trọng
        for sid in ["ep01_scene10_shot04", "ep01_scene10_shot05", "ep01_scene10_shot13"]:
            sdata = shots[sid]
            resolved, take = po.resolve_start_frame_v2(sid, sdata)
            assert resolved is not None, f"{sid} resolved to None"
            assert "kim_trong" in Path(resolved).name.lower(), f"{sid} did not resolve to Kim Trọng: {resolved}"
            assert "thuy_kieu" not in Path(resolved).name.lower(), f"{sid} leaked Thúy Kiều: {resolved}"

    def test_scene06_explicit_shots(self):
        """
        Confirm ep01_scene06_shot03, 04, 06, 10, 12, 14 strictly resolve to Kim Trọng.
        """
        shots = dict(po.get_shots_for_scene("ep01_scene06"))
        assert len(shots) > 0, "Scene 06 has no shots!"

        target_shots = [
            "ep01_scene06_shot03", "ep01_scene06_shot04", "ep01_scene06_shot06",
            "ep01_scene06_shot10", "ep01_scene06_shot12", "ep01_scene06_shot14"
        ]
        for sid in target_shots:
            sdata = shots[sid]
            resolved, take = po.resolve_start_frame_v2(sid, sdata)
            assert resolved is not None, f"{sid} resolved to None"
            assert "kim_trong" in Path(resolved).name.lower(), f"{sid} did not resolve to Kim Trọng: {resolved}"
            assert "thuy_kieu" not in Path(resolved).name.lower(), f"{sid} leaked Thúy Kiều: {resolved}"

    def test_scene05_explicit_shots(self):
        """
        Confirm ep01_scene05_shot13, 16, 24 strictly resolve to Vương Quan.
        """
        shots = dict(po.get_shots_for_scene("ep01_scene05"))
        assert len(shots) > 0, "Scene 05 has no shots!"

        target_shots = ["ep01_scene05_shot13", "ep01_scene05_shot16", "ep01_scene05_shot24"]
        for sid in target_shots:
            sdata = shots[sid]
            resolved, take = po.resolve_start_frame_v2(sid, sdata)
            assert resolved is not None, f"{sid} resolved to None"
            assert "vuong_quan" in Path(resolved).name.lower(), f"{sid} did not resolve to Vương Quan: {resolved}"
            assert "thuy_kieu" not in Path(resolved).name.lower(), f"{sid} leaked Thúy Kiều: {resolved}"


class TestAdversarialMetadataInjection:
    """Stress testing: Inject corrupted character_asset_ref opposite to character anchor."""

    @pytest.mark.parametrize("anchor,corrupted_ref,expected_target,forbidden_target", [
        ("kim_trong", "04_Assets/characters/01_Main_Protagonists/thuy_kieu_maiden_16yo_720p.png", "kim_trong", "thuy_kieu"),
        ("thuy_kieu_maiden", "04_Assets/characters/01_Main_Protagonists/kim_trong_18yo_720p.png", "thuy_kieu", "kim_trong"),
        ("vuong_quan", "04_Assets/characters/01_Main_Protagonists/thuy_kieu_maiden_16yo_720p.png", "vuong_quan", "thuy_kieu"),
        ("vuong_ong", "04_Assets/characters/01_Main_Protagonists/thuy_kieu_maiden_16yo_720p.png", "vuong_ong", "thuy_kieu"),
        ("thuy_van", "04_Assets/characters/01_Main_Protagonists/thuy_kieu_maiden_16yo_720p.png", "thuy_van", "thuy_kieu"),
    ])
    def test_corrupted_ref_opposite_to_anchor(self, anchor, corrupted_ref, expected_target, forbidden_target):
        shot_id = "ep01_scene99_shot01"  # Cut by definition (shot01)
        shot_data = {
            "character_anchor": anchor,
            "character_asset_ref": corrupted_ref,
            "scene_title": f"Test {anchor} scene"
        }
        resolved, take = po.resolve_start_frame_v2(shot_id, shot_data)
        assert resolved is not None
        assert forbidden_target not in Path(resolved).name.lower(), (
            f"Adversarial leak! Anchor={anchor} with corrupted ref={corrupted_ref} returned {resolved}"
        )
        assert expected_target in Path(resolved).name.lower(), (
            f"Bilateral safeguard failed! Expected {expected_target}, got {resolved}"
        )

    @pytest.mark.parametrize("anchor,garbage_ref,expected_target", [
        ("kim_trong", "non_existent_directory/garbage_file.png", "kim_trong"),
        ("thuy_kieu_maiden", "invalid_path/dummy.jpg", "thuy_kieu"),
        ("vuong_quan", "foo/bar/baz.png", "vuong_quan"),
        ("vuong_ong", "not_real.png", "vuong_ong"),
    ])
    def test_nonexistent_corrupted_ref_falls_back_to_anchor_portrait(self, anchor, garbage_ref, expected_target):
        shot_id = "ep01_scene99_shot01"
        shot_data = {
            "character_anchor": anchor,
            "character_asset_ref": garbage_ref,
        }
        resolved, take = po.resolve_start_frame_v2(shot_id, shot_data)
        assert resolved is not None
        assert expected_target in Path(resolved).name.lower()

    def test_empty_and_none_shot_data_robustness(self):
        """Testing with empty dict, None, and shot_data with None values."""
        # Empty dict on an existing shot
        resolved, take = po.resolve_start_frame_v2("ep01_scene10_shot04", {})
        assert resolved is not None
        assert "kim_trong" in Path(resolved).name.lower()

        # None shot_data
        resolved, take = po.resolve_start_frame_v2("ep01_scene10_shot04", None)
        assert resolved is not None
        assert "kim_trong" in Path(resolved).name.lower()

        # Malformed shot_data
        malformed = {"character_anchor": None, "character_asset_ref": None, "scene_title": "Kim Trọng hội ngộ"}
        resolved, take = po.resolve_start_frame_v2("ep01_scene10_shot04", malformed)
        assert resolved is not None
        assert "kim_trong" in Path(resolved).name.lower()
