"""AutoPOE2 - Skill Popup Scanner.

Phát hiện trạng thái hiển thị của Pop-up Menu Actions/Skills/Gem Skills và
xác định vị trí các icon kỹ năng để chọn ngọc tự động.
Tuân thủ Rule 1, Rule 4 (Kiến trúc Module Hóa), Rule 5 (Thực nghiệm 100% dữ liệu thật).
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional, Tuple
from PIL import Image

from src.assistant_tool.skills.skill_constants import (
    SkillPopupGeometry,
    SKILL_POPUP_GEOMETRY,
)


class SkillPopupScanner:
    """Quét và phân tích trạng thái Pop-up Skill menu."""

    def __init__(self, geo: SkillPopupGeometry = SKILL_POPUP_GEOMETRY):
        self.geo = geo

    def is_popup_open(
        self,
        image: Image.Image,
        bbox: Tuple[int, int, int, int],
        threshold: float = 0.65,
    ) -> bool:
        """Kiểm tra xem Pop-up Menu có đang mở tại vùng bbox (left, top, right, bottom) hay không.

        Phân tích đặc trưng màu nền tối mờ đặc thù (RGB < 40) và viền vàng đồng (gold/brown).
        """
        left, top, right, bottom = bbox
        w, h = image.size

        # Bounds check an toàn
        left = max(0, min(left, w - 1))
        top = max(0, min(top, h - 1))
        right = max(left + 1, min(right, w))
        bottom = max(top + 1, min(bottom, h))

        # Crop vùng trung tâm popup (nơi có nền tối đặc thù của menu)
        center_w = right - left
        center_h = bottom - top
        if center_w < 50 or center_h < 50:
            return False

        step_x = max(1, center_w // 25)

        # 1. Đo viền trên cùng (đường ngang màu vàng đồng viền khung popup)
        border_y = max(0, min(top, h - 1))
        border_pixels = [
            image.getpixel((x, border_y))
            for x in range(left + 15, right - 15, step_x)
        ]
        gold_border_matches = sum(
            1
            for p in border_pixels
            if len(p) >= 3 and (60 < p[0] < 140) and (50 < p[1] < 110) and (p[2] < 80)
        )
        gold_ratio = gold_border_matches / max(1, len(border_pixels))

        # 2. Đo dải nền tối ngay dưới viền popup
        interior_y = max(0, min(top + int(center_h * 0.05), h - 1))
        interior_pixels = [
            image.getpixel((x, interior_y))
            for x in range(left + 15, right - 15, step_x)
        ]
        dark_matches = sum(
            1
            for p in interior_pixels
            if len(p) >= 3 and p[0] < 45 and p[1] < 40 and p[2] < 35
        )
        dark_ratio = dark_matches / max(1, len(interior_pixels))

        # Popup mở khi và chỉ khi có viền vàng kim sắc nét và nền nội thất đen tuyền
        return gold_ratio >= 0.55 and dark_ratio >= 0.40

    def get_close_button_pos(self, bbox: Tuple[int, int, int, int]) -> Tuple[int, int]:
        """Tọa độ pixel của nút Close [X] ở góc trên bên phải popup."""
        left, top, right, bottom = bbox
        pw = right - left
        ph = bottom - top
        x = left + int(round(pw * self.geo.close_btn_rel_x))
        y = top + int(round(ph * self.geo.close_btn_rel_y))
        return x, y

    def get_unbind_action_pos(self, bbox: Tuple[int, int, int, int]) -> Tuple[int, int]:
        """Tọa độ pixel của nút ACTIONS -> Clear/Unbind slot (dấu X to)."""
        left, top, right, bottom = bbox
        pw = right - left
        ph = bottom - top
        x = left + int(round(pw * self.geo.unbind_rel_x))
        y = top + int(round(ph * self.geo.unbind_rel_y))
        return x, y

    def get_weapon_skill_pos(
        self, bbox: Tuple[int, int, int, int], col_index: int
    ) -> Tuple[int, int]:
        """Tọa độ pixel của kỹ năng vũ khí trong mục SKILLS (col_index: 0, 1, 2)."""
        left, top, right, bottom = bbox
        pw = right - left
        ph = bottom - top
        col_index = max(0, min(col_index, len(self.geo.skills_col_rel_x) - 1))
        x = left + int(round(pw * self.geo.skills_col_rel_x[col_index]))
        y = top + int(round(ph * self.geo.skills_row_rel_y))
        return x, y

    def get_gem_skill_pos(
        self, bbox: Tuple[int, int, int, int], row: int, col: int
    ) -> Tuple[int, int]:
        """Tọa độ pixel của ngọc kỹ năng trong mục GEM SKILLS (row: 0..N, col: 0..3)."""
        left, top, right, bottom = bbox
        pw = right - left
        ph = bottom - top
        col = max(0, min(col, len(self.geo.gem_skills_col_rel_x) - 1))
        x = left + int(round(pw * self.geo.gem_skills_col_rel_x[col]))
        y_rel = self.geo.gem_skills_start_rel_y + row * self.geo.gem_skills_row_spacing_ratio
        y = top + int(round(ph * y_rel))
        return x, y

    def extract_gem_skills_grid(
        self, image: Image.Image, bbox: Tuple[int, int, int, int], max_rows: int = 2
    ) -> List[Dict[str, Any]]:
        """Trích xuất danh sách các vị trí ngọc kỹ năng trong bảng GEM SKILLS."""
        skills = []
        left, top, right, bottom = bbox
        pw = right - left
        ph = bottom - top

        icon_half_size = int(round(pw * 0.09))  # Bán kính icon ~9% chiều rộng popup

        for r in range(max_rows):
            for c in range(4):
                cx, cy = self.get_gem_skill_pos(bbox, r, c)
                # Bounding box của icon
                ibox = (
                    max(0, cx - icon_half_size),
                    max(0, cy - icon_half_size),
                    min(image.width, cx + icon_half_size),
                    min(image.height, cy + icon_half_size),
                )
                crop_icon = image.crop(ibox)
                # Đánh giá độ sáng/nội dung icon (tránh ô trống đen sì)
                pixels = (
                    list(crop_icon.get_flattened_data())
                    if hasattr(crop_icon, "get_flattened_data")
                    else list(crop_icon.getdata())
                )
                avg_brightness = (
                    sum((p[0] + p[1] + p[2]) / 3.0 for p in pixels) / len(pixels)
                    if pixels
                    else 0.0
                )

                skills.append({
                    "row": r,
                    "col": c,
                    "pos": (cx, cy),
                    "bbox": ibox,
                    "avg_brightness": avg_brightness,
                    "is_active": avg_brightness > 30.0,
                })
        return skills
