"""AutoPOE2 - Unit Tests for Stage 0 Stash Logistics & Restock (Doc 61 / Doc 63 / Doc 69).
==========================================================================================
Kiểm thử toàn diện:
- INV-FOCUS-SAFETY-SEPARATION: Không gửi Win32 keybd_event/mouse_event ra desktop khi is_simulated=True.
- INV-KEY-NO-F-FOR-INTERACT: Mở Stash bằng click LMB có chủ đích.
- INV-STASH-CTRL-CLICK: Cất đồ qua Ctrl+Click có jitter tự nhiên.
- INV-WAYSTONE-ROW1-ONLY: Rút bổ sung Waystone T15 từ Stash Map Tab (Tier XV).
- INV-ATLAS-01: An toàn tại Hideout, từ chối mở Stash khi nhân vật còn đang trong map.
- Chu trình khép kín run_cycle() trên AutonomousMappingCoordinator.
"""

from unittest.mock import MagicMock, patch
import pytest
from PIL import Image

from src.assistant_tool.stash.stage0_stash_handler import Stage0StashHandler, Stage0Result
from src.assistant_tool.stash.stash_constants import StashConfig, StashTabType
from src.assistant_tool.stash.stash_orchestrator import StashOrchestrator
from tools.autonomous_mapping_coordinator import AutonomousMappingCoordinator


def test_stage0_handler_initialization():
    """Kiểm tra khởi tạo Stage0StashHandler với cấu hình chuẩn SSoT 2026."""
    handler = Stage0StashHandler(
        screen_w=2560,
        screen_h=1440,
        target_waystone_tier=15,
        target_waystone_count=5,
        is_simulated=True,
    )
    assert handler.screen_w == 2560
    assert handler.screen_h == 1440
    assert handler.target_waystone_tier == 15
    assert handler.target_waystone_count == 5
    assert handler.is_simulated is True
    assert handler.orchestrator is not None
    assert handler.orchestrator.is_simulated is True


def test_stage0_handler_pre_map_execute_success():
    """Kiểm tra thực thi Stage 0 giai đoạn tiền map (Pre-Map)."""
    fake_img = Image.new("RGB", (2560, 1440), color=(15, 15, 15))
    handler = Stage0StashHandler(is_simulated=True, target_waystone_tier=15)

    handler.orchestrator.run_full_stash_cycle = MagicMock(return_value={
        "success": True,
        "stash_opened": True,
        "tabs_detected": 5,
        "items_deposited": 8,
        "waystone_withdrawn": True,
        "stash_closed": True,
        "error": "",
    })

    res = handler.execute(is_post_map=False)
    assert res["status"] == "SUCCESS"
    assert res["phase"] == "pre_map"
    assert res["stash_opened"] is True
    assert res["items_deposited"] == 8
    assert res["tabs_detected"] == 5
    assert res["waystone_withdrawn"] is True
    assert res["target_tier"] == 15
    assert res["stash_closed"] is True
    handler.orchestrator.run_full_stash_cycle.assert_called_once()


def test_stage0_handler_post_map_execute():
    """Kiểm tra thực thi Stage 0 giai đoạn hậu map (Post-Map Stash Routine)."""
    handler = Stage0StashHandler(is_simulated=True)
    handler.orchestrator.run_full_stash_cycle = MagicMock(return_value={
        "success": True,
        "stash_opened": True,
        "tabs_detected": 4,
        "items_deposited": 12,
        "waystone_withdrawn": False,
        "stash_closed": True,
        "error": "",
    })

    res = handler.execute(is_post_map=True)
    assert res["status"] == "SUCCESS"
    assert res["phase"] == "post_map"
    assert res["items_deposited"] == 12
    assert res["stash_closed"] is True


def test_stage0_handler_inv_focus_safety_separation():
    """INV-FOCUS-SAFETY-SEPARATION: Bảo đảm khi is_simulated=True, cấm 100% Win32 events ra desktop."""
    handler = Stage0StashHandler(is_simulated=True)
    fake_img = Image.new("RGB", (2560, 1440), color=(10, 10, 10))

    with patch("src.common.win32_input._user32.mouse_event") as mock_mouse, \
         patch("src.common.win32_input._user32.keybd_event") as mock_key, \
         patch("src.common.win32_input._user32.SendInput") as mock_send_input:

        # Giả lập run_full_stash_cycle thực tế (không mock cycle)
        with patch.object(handler.orchestrator, "open_stash", return_value=True), \
             patch.object(handler.orchestrator, "scan_tabs", return_value=[]), \
             patch.object(handler.orchestrator, "deposit_inventory_items", return_value=3), \
             patch.object(handler.orchestrator, "withdraw_waystone_if_needed", return_value=True), \
             patch.object(handler.orchestrator, "close_stash", return_value=None):

            res = handler.execute(is_post_map=False)
            assert res["status"] == "SUCCESS"

            # Khẳng định 0% rò rỉ sự kiện chuột/phím phần cứng
            assert mock_mouse.call_count == 0
            assert mock_key.call_count == 0
            assert mock_send_input.call_count == 0


def test_stage0_handler_hideout_check_fail_closed():
    """INV-ATLAS-01: Nếu nhân vật không ở Hideout, từ chối mở Stash và trả về FAILED."""
    handler = Stage0StashHandler(is_simulated=False)
    coordinator = MagicMock()
    coordinator.is_simulated = False
    coordinator.ensure_focus = MagicMock(return_value=True)

    # Giả lập character đang ở trong map "The Western Enigma"
    mock_seeded = MagicMock()
    mock_seeded.area_name = "The Western Enigma"
    coordinator.log_watcher.seed_latest_playable_zone.return_value = mock_seeded

    res = handler.execute(coordinator=coordinator)
    assert res["status"] == "FAILED"
    assert "không phải Hideout" in res["error"]
    assert res["stash_opened"] is False


def test_stage0_handler_withdraw_waystone_t15_deficit():
    """Kiểm tra tính toán số lượng thiếu hụt và rút đúng Waystone T15."""
    handler = Stage0StashHandler(is_simulated=True, target_waystone_tier=15, target_waystone_count=5)
    handler.orchestrator.withdraw_waystone_if_needed = MagicMock(return_value=True)

    # Túi đang có 2 Waystones -> Cần rút 3
    needed = 5 - 2
    success, count = handler.withdraw_waystone_t15(needed=needed)
    assert success is True
    assert count == 3
    handler.orchestrator.withdraw_waystone_if_needed.assert_called_once_with(
        img=None,
        current_waystones_in_bag=2,
    )


def test_coordinator_run_cycle_delegation():
    """Kiểm tra AutonomousMappingCoordinator.run_cycle() kích hoạt khép kín toàn bộ chu trình."""
    coordinator = AutonomousMappingCoordinator(is_simulated=True)
    coordinator.ensure_focus = MagicMock(return_value=True)
    coordinator.dismiss_modals = MagicMock()
    coordinator.check_active_portal_in_hideout = MagicMock(return_value=None)

    # Mock các stages
    coordinator.stage0_handler.execute = MagicMock(return_value={
        "status": "SUCCESS",
        "stash_opened": True,
        "items_deposited": 4,
        "waystone_withdrawn": True,
        "stash_closed": True,
    })
    coordinator.execute_stage1_precheck = MagicMock(return_value={
        "status": "SUCCESS",
        "selected_slot": (0, 0, 1731, 822, 65.5),
    })
    coordinator.execute_stage2_map_device = MagicMock(return_value={"status": "SUCCESS"})
    coordinator.execute_stage3_atlas_activation = MagicMock(return_value={"status": "SUCCESS"})
    coordinator.execute_stage4_map_entrance = MagicMock(return_value={"status": "SUCCESS", "entered_zone": "The Western Enigma"})
    coordinator.execute_stage5_map_clear = MagicMock(return_value={"status": "SUCCESS", "runner_instance": None, "runner_result": {}})
    coordinator.execute_stage6_portal_return = MagicMock(return_value={"status": "SUCCESS"})

    report = coordinator.run_cycle(
        target_slot_idx=0,
        enable_stashing=True,
        enable_post_stashing=True,
        allow_portal_bypass=False,
    )

    assert report["status"] == "SUCCESS"
    assert "STAGE0_STASH" in report["stages_completed"]
    assert "STAGE1_PRECHECK" in report["stages_completed"]
    assert "STAGE2_MAP_DEVICE" in report["stages_completed"]
    assert "STAGE3_ATLAS_ACTIVATION" in report["stages_completed"]
    assert "STAGE4_MAP_ENTRANCE" in report["stages_completed"]
    assert "STAGE5_MAP_CLEAR" in report["stages_completed"]
    assert "STAGE6_PORTAL_RETURN" in report["stages_completed"]
    assert "STAGE0_POST_STASH" in report["stages_completed"]

    # Đã thực hiện cả 2 lượt Stage 0: Pre-map và Post-map
    assert coordinator.stage0_handler.execute.call_count == 2
