"""
Test Suite: Milestone M2 - Archival & Workspace Hygiene
Project: Thập Ngũ Niên (The Fifteen Springs) - Ep01 Re-production Campaign

Verifies:
1. Exactly 184 Ep01 legacy video files safely migrated to 04_Assets/archive/ep01_legacy_v1/
2. Exactly 0 files with 'ep01' remaining in 04_Assets/videos/
3. Exactly 0 directories starting with 'ep01' remaining in 04_Assets/keyframes/ and root keyframe purged
4. Legal IP documentation README.md exists in archive and exceeds 1,000 bytes with required legal citations
5. All 14 core character portraits in 04_Assets/characters/ exist, are valid PNG images with correct dimensions
6. Non-Ep01 videos and keyframes are completely unharmed
"""

import os
from pathlib import Path
import pytest
from PIL import Image

PROJECT_ROOT = Path(__file__).resolve().parent.parent
VIDEOS_DIR = PROJECT_ROOT / "04_Assets" / "videos"
KEYFRAMES_DIR = PROJECT_ROOT / "04_Assets" / "keyframes"
CHARACTERS_DIR = PROJECT_ROOT / "04_Assets" / "characters"
ARCHIVE_DIR = PROJECT_ROOT / "04_Assets" / "archive" / "ep01_legacy_v1"

CORE_EP01_CHARACTERS = [
    ("01_Main_Protagonists/thuy_kieu_maiden_16yo_720p.png", (1280, 720)),
    ("01_Main_Protagonists/thuy_kieu_maiden_16yo_master.png", (1376, 768)),
    ("01_Main_Protagonists/thuy_van_maiden_16yo_720p.png", (1280, 720)),
    ("01_Main_Protagonists/thuy_van_maiden_16yo_master.png", (1376, 768)),
    ("01_Main_Protagonists/kim_trong_18yo_720p.png", (1280, 720)),
    ("01_Main_Protagonists/kim_trong_18yo_master.png", (1376, 768)),
    ("02_Vuong_Family_And_Fate/vuong_quan_16yo_720p.png", (1280, 720)),
    ("02_Vuong_Family_And_Fate/vuong_quan_16yo_master.png", (1376, 768)),
    ("02_Vuong_Family_And_Fate/vuong_ong_55yo_720p.png", (1280, 720)),
    ("02_Vuong_Family_And_Fate/vuong_ong_55yo_master.png", (1376, 768)),
    ("02_Vuong_Family_And_Fate/vuong_ba_50yo_720p.png", (1280, 720)),
    ("02_Vuong_Family_And_Fate/vuong_ba_50yo_master.png", (1376, 768)),
    ("02_Vuong_Family_And_Fate/dam_tien_720p.png", (1280, 720)),
    ("02_Vuong_Family_And_Fate/dam_tien_master.png", (1376, 768)),
]


def test_archive_ep01_video_count():
    """Assert exactly 184 Ep01 video files exist in 04_Assets/archive/ep01_legacy_v1/."""
    assert ARCHIVE_DIR.exists(), f"Archive directory does not exist: {ARCHIVE_DIR}"
    assert ARCHIVE_DIR.is_dir(), f"Archive path is not a directory: {ARCHIVE_DIR}"

    archived_videos = [f for f in os.listdir(ARCHIVE_DIR) if f.lower().endswith(".mp4")]
    assert len(archived_videos) == 184, (
        f"Expected exactly 184 video files in {ARCHIVE_DIR}, but found {len(archived_videos)}"
    )

    # Check non-empty files and significant aggregate size (> 2.0 GB)
    total_size = sum((ARCHIVE_DIR / f).stat().st_size for f in archived_videos)
    assert total_size > 2_000_000_000, (
        f"Archive total video size too small ({total_size} bytes), data corruption suspected"
    )

    for vid in archived_videos:
        p = ARCHIVE_DIR / vid
        assert p.stat().st_size > 500_000, f"Video file {vid} suspiciously small ({p.stat().st_size} bytes)"


def test_videos_ep01_purged():
    """Assert 0 files with 'ep01' remain in 04_Assets/videos/."""
    assert VIDEOS_DIR.exists(), f"Videos directory does not exist: {VIDEOS_DIR}"

    ep01_remaining = [f for f in os.listdir(VIDEOS_DIR) if "ep01" in f.lower()]
    assert len(ep01_remaining) == 0, (
        f"Expected 0 Ep01 files remaining in {VIDEOS_DIR}, but found {len(ep01_remaining)}: {ep01_remaining}"
    )


def test_keyframes_ep01_purged():
    """Assert 0 directories starting with 'ep01' remaining in 04_Assets/keyframes/ and root file removed."""
    assert KEYFRAMES_DIR.exists(), f"Keyframes directory does not exist: {KEYFRAMES_DIR}"

    ep01_dirs = [
        d for d in os.listdir(KEYFRAMES_DIR)
        if (KEYFRAMES_DIR / d).is_dir() and d.lower().startswith("ep01")
    ]
    assert len(ep01_dirs) == 0, (
        f"Expected 0 Ep01 keyframe directories remaining in {KEYFRAMES_DIR}, found {len(ep01_dirs)}: {ep01_dirs[:5]}"
    )

    root_ep01_file = KEYFRAMES_DIR / "ep01_scene03_start_720p.png"
    assert not root_ep01_file.exists(), (
        f"Root keyframe file {root_ep01_file} was not purged"
    )

    ep01_files_any = [
        f for f in os.listdir(KEYFRAMES_DIR)
        if "ep01" in f.lower()
    ]
    assert len(ep01_files_any) == 0, (
        f"Found Ep01 files remaining in keyframes root: {ep01_files_any}"
    )


def test_archive_readme_legal_documentation():
    """Assert README.md exists in archive, is > 1000 bytes, and contains required legal and creative justification."""
    readme_path = ARCHIVE_DIR / "README.md"
    assert readme_path.exists(), f"README.md missing in {ARCHIVE_DIR}"
    assert readme_path.is_file(), f"README.md is not a file: {readme_path}"

    size = readme_path.stat().st_size
    assert size > 1000, f"README.md size ({size} bytes) is less than required 1000 bytes"

    content = readme_path.read_text(encoding="utf-8")

    # Legal foundations
    assert "Điều 4 khoản 8" in content, "Missing reference to Article 4(8) of Vietnamese IP Law"
    assert "Điều 14" in content, "Missing reference to Article 14 of Vietnamese IP Law"
    assert "Điều 20" in content, "Missing reference to Article 20 of Vietnamese IP Law"
    assert "Điều 43" in content, "Missing reference to Article 43 of Vietnamese IP Law"

    # Author and IP details
    assert "NGUYỄN SĨ SƠN" in content, "Missing Author name Nguyễn Sĩ Sơn"
    assert "031090010018" in content, "Missing Author CCCD number"
    assert "Nguyễn Du" in content, "Missing reference to Nguyễn Du"

    # Human-in-the-Loop creative evidence
    assert "Human-in-the-Loop" in content or "Human Agency" in content, (
        "Missing Human-in-the-Loop creative workflow explanation"
    )
    assert "Zero Permanent Deletion" in content, "Missing Zero Permanent Deletion rationale"
    assert "184" in content, "Missing 184 file inventory count"


def test_character_portraits_unharmed():
    """Assert all 14 core Ep01 character portraits exist, are valid PNG images with expected dimensions."""
    assert CHARACTERS_DIR.exists(), f"Characters directory does not exist: {CHARACTERS_DIR}"

    for rel_path, expected_dims in CORE_EP01_CHARACTERS:
        full_path = CHARACTERS_DIR / rel_path
        assert full_path.exists(), f"Character portrait missing: {rel_path}"
        assert full_path.is_file(), f"Character portrait not a file: {rel_path}"
        assert full_path.stat().st_size > 500_000, f"Character portrait suspiciously small: {rel_path}"

        # Verify image validity and dimensions
        with Image.open(full_path) as img:
            assert img.format == "PNG", f"Expected PNG format for {rel_path}, got {img.format}"
            assert img.size == expected_dims, (
                f"Dimension mismatch for {rel_path}: expected {expected_dims}, got {img.size}"
            )

    # Invariant: exactly 62 total character files
    total_char_files = sum(len(files) for _, _, files in os.walk(CHARACTERS_DIR))
    assert total_char_files == 62, f"Total character assets altered! Expected 62, found {total_char_files}"


def test_non_ep01_assets_unharmed():
    """Assert non-Ep01 videos and keyframes are completely unharmed."""
    # Non-Ep01 videos in 04_Assets/videos/
    non_ep01_videos = [f for f in os.listdir(VIDEOS_DIR) if "ep01" not in f.lower()]
    assert len(non_ep01_videos) == 118, (
        f"Non-Ep01 videos altered! Expected exactly 118, found {len(non_ep01_videos)}"
    )

    # Keyframe dirs for non-Ep01 episodes
    non_ep01_kf_dirs = [
        d for d in os.listdir(KEYFRAMES_DIR)
        if (KEYFRAMES_DIR / d).is_dir() and not d.lower().startswith("ep01")
    ]
    assert len(non_ep01_kf_dirs) == 67, (
        f"Non-Ep01 keyframe dirs altered! Expected exactly 67, found {len(non_ep01_kf_dirs)}"
    )

    # Keyframe root files for non-Ep01
    non_ep01_root_files = [f for f in os.listdir(KEYFRAMES_DIR) if (KEYFRAMES_DIR / f).is_file()]
    assert len(non_ep01_root_files) == 10, (
        f"Non-Ep01 keyframe root files altered! Expected 10, found {len(non_ep01_root_files)}"
    )


if __name__ == "__main__":
    import sys
    pytest_args = [__file__, "-v"]
    sys.exit(pytest.main(pytest_args))
