"""
Unit tests for FreeExile Design Pipeline Manager and Cross-Department Workflow.
Tests complete lifecycle: Create -> Scan -> Dispatch -> Submit -> QA Audit -> CEO Audit -> Sync.
"""

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

from tools.asset_pipeline.design_pipeline_manager import (
    ApprovalVerdict,
    AssetCategory,
    DesignPipelineManager,
    Priority,
    RequestStatus,
    is_power_of_two,
)


@pytest.fixture
def temp_workspace(tmp_path: Path) -> DesignPipelineManager:
    """Creates a temporary workspace with full pipeline directory hierarchy."""
    ws = tmp_path / "FreeExile_Test"
    ws.mkdir(parents=True, exist_ok=True)
    mgr = DesignPipelineManager(workspace_root=ws)
    return mgr


def test_power_of_two() -> None:
    assert is_power_of_two(1) is True
    assert is_power_of_two(2) is True
    assert is_power_of_two(64) is True
    assert is_power_of_two(256) is True
    assert is_power_of_two(512) is True
    assert is_power_of_two(1024) is True
    assert is_power_of_two(0) is False
    assert is_power_of_two(3) is False
    assert is_power_of_two(250) is False


def test_create_and_scan_inbox(temp_workspace: DesignPipelineManager) -> None:
    mgr = temp_workspace

    # Create 3 requests with different priorities
    req1 = mgr.create_request(
        request_id="DRQ-TEST-001",
        title="Icon Linh Thạch Hỗn Nguyên",
        source_doc="docs/ORIGINAL_SYSTEMS_AND_ECONOMY.md",
        requesting_dept="Lead Systems Designer",
        category=AssetCategory.SPRITE,
        priority=Priority.HIGH,
        assigned_agent="isometric_animator",
        lore_context="Linh thạch bản vị cốt lõi.",
        specs_dict={"Resolution": "256x256", "Format": "PNG"},
        deliverables=["chaos_stone.png", "chaos_stone_normal.png"],
    )

    req2 = mgr.create_request(
        request_id="DRQ-TEST-002",
        title="UI Rương Luân Hồi Chỉ Rút",
        source_doc="docs/SEASONAL_LEAGUE_RESET_ARCHITECTURE.md",
        requesting_dept="Lead Documentation Architect",
        category=AssetCategory.UI,
        priority=Priority.CRITICAL,
        assigned_agent="mobile_ui_designer",
        lore_context="Rương kết chuyển mùa giải.",
        specs_dict={"Resolution": "512x512", "Format": "WebP"},
        deliverables=["remove_only_stash.png"],
    )

    req3 = mgr.create_request(
        request_id="DRQ-TEST-003",
        title="Trang Trí Môi Trường Đạo Quán",
        source_doc="docs/GAME_ENGINE_ARCHITECTURE.md",
        requesting_dept="Client Architect",
        category=AssetCategory.CONCEPT,
        priority=Priority.LOW,
        assigned_agent="concept_artist",
        lore_context="Bối cảnh ngoại cảnh.",
        specs_dict={"Resolution": "1024x1024", "Format": "PNG"},
        deliverables=["daoist_temple_concept.png"],
    )

    inbox = mgr.scan_inbox()
    assert len(inbox) == 3
    # Ordered by priority rank: CRITICAL (0), HIGH (1), LOW (3)
    assert inbox[0].request_id == "DRQ-TEST-002"
    assert inbox[1].request_id == "DRQ-TEST-001"
    assert inbox[2].request_id == "DRQ-TEST-003"


def test_dispatch_request(temp_workspace: DesignPipelineManager) -> None:
    mgr = temp_workspace
    req = mgr.create_request(
        request_id="DRQ-DISPATCH-001",
        title="VFX Huyễn Ảnh Bộ i-frame",
        source_doc="docs/GAME_ENGINE_ARCHITECTURE.md",
        requesting_dept="Combat Designer",
        category=AssetCategory.VFX,
        priority=Priority.CRITICAL,
        assigned_agent="art_ui_director",
        lore_context="Hiệu ứng lướt tàn ảnh né đòn.",
        specs_dict={"Shader": "Apple Metal Compute"},
        deliverables=["phantom_dodge.metal", "dodge_trail.png"],
    )

    assert (mgr.inbox_dir / "DRQ-DISPATCH-001.md").exists()

    # Dispatch and reassign to vfx_tech_artist
    dispatched = mgr.dispatch_request("DRQ-DISPATCH-001", assigned_agent="vfx_tech_artist")

    assert not (mgr.inbox_dir / "DRQ-DISPATCH-001.md").exists()
    assert (mgr.in_progress_dir / "DRQ-DISPATCH-001.md").exists()
    assert dispatched.status == RequestStatus.IN_PROGRESS
    assert dispatched.assigned_agent == "vfx_tech_artist"


def test_submit_and_qa_technical_audit_pass(temp_workspace: DesignPipelineManager) -> None:
    mgr = temp_workspace

    req = mgr.create_request(
        request_id="DRQ-QA-PASS-001",
        title="Icon Đan Dược Chân Võ",
        source_doc="docs/ORIGINAL_SYSTEMS_AND_ECONOMY.md",
        requesting_dept="Systems Designer",
        category=AssetCategory.SPRITE,
        priority=Priority.HIGH,
        assigned_agent="isometric_animator",
        lore_context="Đan dược bổ trợ.",
        specs_dict={"Resolution": "256x256"},
        deliverables=["pill_icon.png", "pill_icon_normal.png"],
    )

    mgr.dispatch_request("DRQ-QA-PASS-001")

    # Generate test image files in pending assets directory
    asset_dir = mgr.assets_pending / "DRQ-QA-PASS-001"
    asset_dir.mkdir(parents=True, exist_ok=True)

    img_albedo = Image.new("RGBA", (256, 256), (200, 100, 50, 255))
    img_albedo.save(asset_dir / "pill_icon.png")

    img_normal = Image.new("RGBA", (256, 256), (128, 128, 255, 255))
    img_normal.save(asset_dir / "pill_icon_normal.png")

    # Submit for review
    submitted = mgr.submit_for_review("DRQ-QA-PASS-001", ["pill_icon.png", "pill_icon_normal.png"])
    assert submitted.status == RequestStatus.PENDING_REVIEW
    assert (mgr.pending_review_dir / "DRQ-QA-PASS-001.md").exists()

    # QA Audit
    passed, notes, deliverables = mgr.qa_technical_audit("DRQ-QA-PASS-001")
    assert passed is True
    assert len(deliverables) == 2
    assert all(d.is_power_of_two for d in deliverables)

    # Content should be marked PASS in Cấp 1
    content = (mgr.pending_review_dir / "DRQ-QA-PASS-001.md").read_text(encoding="utf-8")
    assert "- **Kết Quả Cấp 1**: `PASS`" in content


def test_qa_technical_audit_fail_on_non_power_of_two(temp_workspace: DesignPipelineManager) -> None:
    mgr = temp_workspace

    mgr.create_request(
        request_id="DRQ-QA-FAIL-001",
        title="Icon Kích Thước Lỗi",
        source_doc="docs/GAME_ENGINE_ARCHITECTURE.md",
        requesting_dept="Test Dept",
        category=AssetCategory.SPRITE,
        priority=Priority.MEDIUM,
        assigned_agent="isometric_animator",
        lore_context="Test non-POT size.",
        specs_dict={"Resolution": "250x250"},
        deliverables=["bad_size.png"],
    )

    mgr.dispatch_request("DRQ-QA-FAIL-001")

    asset_dir = mgr.assets_pending / "DRQ-QA-FAIL-001"
    asset_dir.mkdir(parents=True, exist_ok=True)

    # 250x250 is NOT power of two
    img_bad = Image.new("RGBA", (250, 250), (255, 0, 0, 255))
    img_bad.save(asset_dir / "bad_size.png")

    mgr.submit_for_review("DRQ-QA-FAIL-001", ["bad_size.png"])

    passed, notes, deliverables = mgr.qa_technical_audit("DRQ-QA-FAIL-001")
    assert passed is False
    assert "dimensions (250x250) are not power of 2" in notes

    # Should have moved to rejected/
    assert not (mgr.pending_review_dir / "DRQ-QA-FAIL-001.md").exists()
    assert (mgr.rejected_dir / "DRQ-QA-FAIL-001.md").exists()


def test_ceo_aesthetic_audit_full_approval(temp_workspace: DesignPipelineManager) -> None:
    mgr = temp_workspace

    mgr.create_request(
        request_id="DRQ-CEO-APP-001",
        title="Banner Mùa Giải Mới",
        source_doc="docs/SEASONAL_LEAGUE_RESET_ARCHITECTURE.md",
        requesting_dept="Lead Documentation Architect",
        category=AssetCategory.UI,
        priority=Priority.CRITICAL,
        assigned_agent="mobile_ui_designer",
        lore_context="Khởi đầu mùa giải Thiên Đạo Luân Hồi.",
        specs_dict={"Resolution": "512x512"},
        deliverables=["season_banner.png"],
    )

    mgr.dispatch_request("DRQ-CEO-APP-001")

    asset_dir = mgr.assets_pending / "DRQ-CEO-APP-001"
    asset_dir.mkdir(parents=True, exist_ok=True)

    img = Image.new("RGBA", (512, 512), (30, 20, 40, 255))
    img.save(asset_dir / "season_banner.png")

    mgr.submit_for_review("DRQ-CEO-APP-001", ["season_banner.png"])

    # QA pass
    qa_pass, _, _ = mgr.qa_technical_audit("DRQ-CEO-APP-001")
    assert qa_pass is True

    # CEO approval and sync to client
    approved_req = mgr.ceo_aesthetic_audit(
        request_id="DRQ-CEO-APP-001",
        approver="studio_producer",
        verdict=ApprovalVerdict.APPROVE,
        notes="Phong cách Cổ Võ Hắc Ám tuyệt đẹp!",
        sync_to_client_subfolder="seasons",
    )

    assert approved_req.status == RequestStatus.APPROVED
    assert (mgr.approved_dir / "DRQ-CEO-APP-001.md").exists()
    assert not (mgr.pending_review_dir / "DRQ-CEO-APP-001.md").exists()

    # Asset copied to approved and client webapp
    assert (mgr.assets_approved / "DRQ-CEO-APP-001" / "season_banner.png").exists()
    assert (mgr.client_webapp_assets / "seasons" / "season_banner.png").exists()


def test_pipeline_summary_and_report(temp_workspace: DesignPipelineManager) -> None:
    mgr = temp_workspace
    mgr.create_request(
        request_id="DRQ-SUM-001",
        title="Test Request",
        source_doc="docs/GAME_ENGINE_ARCHITECTURE.md",
        requesting_dept="QA",
        category=AssetCategory.CONCEPT,
        priority=Priority.LOW,
        assigned_agent="concept_artist",
        lore_context="Summary test",
        specs_dict={},
        deliverables=[],
    )

    summary = mgr.get_pipeline_summary()
    assert summary["inbox"] == 1
    assert summary["in_progress"] == 0

    report = mgr.generate_status_report()
    assert "FREEEXILE DESIGN PIPELINE STATUS REPORT" in report
    assert "DRQ-SUM-001" in report
