"""
AutoPOE2 - Waystone Loader Guard & Cursor Safety Interlock (Doc 48 / Doc 56)
=============================================================================
Khối bảo vệ an toàn cho quy trình Stage 3: Atlas Node Selection & Waystone Loading.
Giải quyết triệt để sự cố trôi chuột vô tình nhấc item dính vào con trỏ (popup 'You cannot drop that item here').

Tuân thủ bất biến kiến trúc:
- INV-INPUT-ABS-MOUSE: Thao tác chuột dứt khoát với tọa độ tuyệt đối, zero mouse drag.
- INV-CURSOR-SAFETY: Kiểm tra và tự động giải phóng/đặt lại item dính trên chuột về ô túi đồ trước khi click TRAVERSE.
- Rule 4: Module hóa độc lập, trần file < 500 dòng.
"""

from __future__ import annotations

import ctypes
from ctypes import wintypes
import os
import time
from typing import Any, Callable, Optional, Tuple


class WaystoneLoaderGuard:
    """
    Bộ bảo vệ quy trình nạp Waystone và khóa an toàn con trỏ chuột.
    """

    VK_CONTROL = 0x11
    SC_CONTROL = 0x1D
    KEYEVENTF_KEYUP = 0x0002
    MOUSEEVENTF_LEFTDOWN = 0x0002
    MOUSEEVENTF_LEFTUP = 0x0004

    @staticmethod
    def is_item_stuck_on_cursor(img_path: Optional[str]) -> bool:
        """
        Kiểm tra xem có vật phẩm nào đang dính vào con trỏ chuột hoặc có popup cảnh báo:
        'You cannot drop that item here' / 'cannot drop' xuất hiện trên màn hình hay không.
        """
        if not img_path or not os.path.exists(img_path):
            return False
        try:
            from PIL import Image
            from src.common import safe_recognize_pil_sync
            img = Image.open(img_path)
            res = safe_recognize_pil_sync(img)
            for line in res.get("lines", []):
                t = line.get("text", "").upper()
                if any(k in t for k in ["CANNOT DROP", "DROP THAT ITEM", "CAN NOT DROP", "YOU CANNOT DROP"]):
                    return True
        except Exception:
            pass
        return False

    @classmethod
    def crisp_ctrl_click(
        cls,
        screen_x: int,
        screen_y: int,
        hold_ms: float = 0.05,
        delay_after: float = 0.3,
        is_simulated: bool = False,
        hwnd: Optional[int] = None,
        use_post_message: bool = False,
    ) -> bool:
        """
        Thực hiện lệnh Ctrl+Click dứt khoát (nhấn Ctrl -> Click LMB -> Nhả Ctrl, không phát sinh mouse drag).
        Khóa chặt tọa độ chuột, triệt tiêu hiện tượng trôi chuột gây nhấc nhầm item lên con trỏ.
        Hỗ trợ cả chế độ Foreground Win32 SendInput/mouse_event lẫn Background PostMessageW.
        """
        if is_simulated:
            return True

        if use_post_message and hwnd:
            from src.common.win32_input import post_message_ctrl_click
            return post_message_ctrl_click(hwnd, int(screen_x), int(screen_y), hold_ms=hold_ms, delay_after=delay_after)

        user32 = ctypes.windll.user32

        # 1. Đặt vị trí chuột chính xác và dừng ổn định
        user32.SetCursorPos(int(screen_x), int(screen_y))
        time.sleep(0.06)

        # 2. Nhấn và giữ phím Ctrl
        user32.keybd_event(cls.VK_CONTROL, cls.SC_CONTROL, 0, 0)
        time.sleep(0.05)

        # 3. Đảm bảo chuột không bị trôi trước khi nhấp chuột trái
        user32.SetCursorPos(int(screen_x), int(screen_y))

        # 4. Nhấn chuột trái (LMB Down)
        user32.mouse_event(cls.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
        time.sleep(hold_ms)

        # 5. Nhả chuột trái (LMB Up) ngay tại tọa độ cố định (chống mouse drag tuyệt đối)
        user32.mouse_event(cls.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
        time.sleep(0.05)

        # 6. Nhả phím Ctrl
        user32.keybd_event(cls.VK_CONTROL, cls.SC_CONTROL, cls.KEYEVENTF_KEYUP, 0)

        if delay_after > 0:
            time.sleep(delay_after)
        return True

    @classmethod
    def recover_cursor_item_to_inventory(
        cls,
        click_func: Callable[[int, int], Any],
        slot_x: int,
        slot_y: int,
        press_key_func: Optional[Callable[[int, int], Any]] = None,
        delay_after: float = 0.4,
    ) -> bool:
        """
        Tự động hoàn trả item đang dính trên con trỏ chuột về lại ô túi đồ (slot_x, slot_y).
        Giải quyết triệt để sự cố 'You cannot drop that item here'.
        """
        # Nhấp chuột trái vào ô túi đồ để đặt item xuống
        click_func(slot_x, slot_y)
        time.sleep(delay_after)

        # Gửi phím ESC nhẹ để giải phóng tooltip hoặc hủy trạng thái treo nếu cần
        if press_key_func:
            press_key_func(0x1B, 0x01)
            time.sleep(0.15)
        return True
