"""AutoPOE2 - Skill Binder Engine.

Điều phối quy trình gán ngọc kỹ năng và kỹ năng vũ khí vào các slot Action Bar.
Sử dụng Win32 PostMessage chạy ngầm, không cướp chuột hay làm gián đoạn người dùng.
Tuân thủ Rule 1, Rule 4 (Kiến trúc Module Hóa), Rule 7 (Chuẩn người chơi thật).
"""

from __future__ import annotations

import ctypes
from ctypes import wintypes
import time
from typing import Optional, Tuple

from src.common.win32_input import (
    post_message_click,
    post_message_key,
    VK_ESCAPE,
)
from src.assistant_tool.skills.skill_constants import (
    ActionBarSlot,
    SkillPopupGeometry,
    SKILL_POPUP_GEOMETRY,
    get_slot_client_pos,
    get_popup_bounding_box,
)
from src.assistant_tool.skills.skill_popup_scanner import SkillPopupScanner

_user32 = ctypes.windll.user32


class SkillBinder:
    """Động cơ gán phím kỹ năng tự động chạy ngầm trong POE2."""

    def __init__(
        self,
        hwnd: int,
        scanner: Optional[SkillPopupScanner] = None,
        geo: SkillPopupGeometry = SKILL_POPUP_GEOMETRY,
    ):
        self.hwnd = hwnd
        self.geo = geo
        self.scanner = scanner or SkillPopupScanner(geo=self.geo)

    def get_client_size(self) -> Tuple[int, int]:
        """Lấy kích thước chiều rộng và chiều cao của Client Area."""
        if not self.hwnd or not _user32.IsWindow(self.hwnd):
            raise ValueError(f"HWND {self.hwnd} không hợp lệ hoặc cửa sổ đã đóng.")
        rect = wintypes.RECT()
        _user32.GetClientRect(self.hwnd, ctypes.byref(rect))
        w = rect.right - rect.left
        h = rect.bottom - rect.top
        return max(1, w), max(1, h)

    def open_slot_popup(self, slot: ActionBarSlot, delay: float = 0.20) -> Tuple[int, int]:
        """Gửi click ngầm vào ô slot trên Action Bar để mở Pop-up Actions/Skills.
        
        Trả về tọa độ (client_x, client_y) đã click.
        """
        cw, ch = self.get_client_size()
        sx, sy = get_slot_client_pos(slot, cw, ch)
        post_message_click(self.hwnd, sx, sy, button="left", hold_ms=0.04, delay_after=delay)
        return sx, sy

    def close_popup(self, delay: float = 0.15) -> bool:
        """Đóng Pop-up Actions/Skills bằng cách gửi phím ESC ngầm."""
        return post_message_key(self.hwnd, VK_ESCAPE, dwell_ms=0.05, delay_after=delay)

    def unbind_slot(self, slot: ActionBarSlot, delay_between: float = 0.20) -> bool:
        """Gỡ bỏ kỹ năng hiện tại khỏi slot (chuyển thành ô trống) qua nút ACTIONS -> X."""
        cw, ch = self.get_client_size()
        self.open_slot_popup(slot, delay=delay_between)

        bbox = get_popup_bounding_box(slot, cw, ch, geo=self.geo)
        ux, uy = self.scanner.get_unbind_action_pos(bbox)
        post_message_click(self.hwnd, ux, uy, button="left", hold_ms=0.04, delay_after=delay_between)
        self.close_popup(delay=0.10)
        return True

    def bind_gem_skill(
        self,
        slot: ActionBarSlot,
        row: int,
        col: int,
        delay_between: float = 0.20,
    ) -> bool:
        """Gán một ngọc kỹ năng trong bảng GEM SKILLS (hàng row, cột col) vào slot mong muốn."""
        cw, ch = self.get_client_size()
        self.open_slot_popup(slot, delay=delay_between)

        bbox = get_popup_bounding_box(slot, cw, ch, geo=self.geo)
        gx, gy = self.scanner.get_gem_skill_pos(bbox, row=row, col=col)
        post_message_click(self.hwnd, gx, gy, button="left", hold_ms=0.04, delay_after=delay_between)
        # Bấm ESC để chắc chắn menu đóng sau khi gán
        self.close_popup(delay=0.10)
        return True

    def bind_weapon_skill(
        self,
        slot: ActionBarSlot,
        col_index: int,
        delay_between: float = 0.20,
    ) -> bool:
        """Gán kỹ năng vũ khí trong bảng SKILLS (cột col_index: 0, 1, 2) vào slot mong muốn."""
        cw, ch = self.get_client_size()
        self.open_slot_popup(slot, delay=delay_between)

        bbox = get_popup_bounding_box(slot, cw, ch, geo=self.geo)
        wx, wy = self.scanner.get_weapon_skill_pos(bbox, col_index=col_index)
        post_message_click(self.hwnd, wx, wy, button="left", hold_ms=0.04, delay_after=delay_between)
        self.close_popup(delay=0.10)
        return True
