import logging
from typing import Dict

from PyQt6.QtCore import Qt
from PyQt6.QtGui import QMouseEvent
from PyQt6.QtWidgets import QWidget

logger = logging.getLogger(__name__)


class ResizeHandle(QWidget):
    """Transparent widget used to resize the frameless window."""

    def __init__(self, edge_name: str, main_window: "HollowSteamApp"):
        super().__init__(main_window)
        self.edge_name = edge_name
        self.main_window = main_window
        self.resizing = False
        self.resize_start_pos = None
        self.resize_start_geom = None
        self.setStyleSheet("background: transparent;")

    def mousePressEvent(self, event: QMouseEvent) -> None:
        if event.button() != Qt.MouseButton.LeftButton:
            return

        window = self.main_window.windowHandle()
        edge = self._get_qt_edge()

        if window and window.isExposed() and window.startSystemResize(edge):
            event.accept()
            return

        self.resizing = True
        self.resize_start_pos = event.globalPosition().toPoint()
        self.resize_start_geom = self.main_window.geometry()
        self.grabMouse()
        event.accept()

    def mouseMoveEvent(self, event: QMouseEvent) -> None:
        if not self.resizing:
            return

        delta = event.globalPosition().toPoint() - self.resize_start_pos
        geom = self.resize_start_geom
        x, y, w, h = geom.x(), geom.y(), geom.width(), geom.height()

        if "right" in self.edge_name:
            w += delta.x()
        if "bottom" in self.edge_name:
            h += delta.y()
        if "left" in self.edge_name:
            x += delta.x()
            w -= delta.x()
        if "top" in self.edge_name:
            y += delta.y()
            h -= delta.y()

        w = max(w, self.main_window.minimumWidth())
        h = max(h, self.main_window.minimumHeight())

        self.main_window.setGeometry(x, y, w, h)

    def mouseReleaseEvent(self, event: QMouseEvent) -> None:
        if self.resizing:
            self.releaseMouse()
            self.resizing = False
        event.accept()

    def _get_qt_edge(self) -> Qt.Edge:
        edge_map = {
            "left": Qt.Edge.LeftEdge,
            "right": Qt.Edge.RightEdge,
            "top": Qt.Edge.TopEdge,
            "bottom": Qt.Edge.BottomEdge,
            "top_left": Qt.Edge.LeftEdge,
            "top_right": Qt.Edge.RightEdge,
            "bottom_left": Qt.Edge.LeftEdge,
            "bottom_right": Qt.Edge.RightEdge,
        }
        return edge_map.get(self.edge_name, Qt.Edge.RightEdge)


def setup_resize_handles(main_window: "HollowSteamApp") -> Dict[str, ResizeHandle]:
    """Setup invisible resize handles for all edges and corners."""
    handles: Dict[str, ResizeHandle] = {}
    edges = [
        "top_left",
        "top_right",
        "bottom_left",
        "bottom_right",
        "left",
        "right",
        "top",
        "bottom",
    ]

    for name in edges:
        handle = ResizeHandle(name, main_window)
        handle.setCursor(_get_cursor_for_edge(name))
        handles[name] = handle

    return handles


def _get_cursor_for_edge(edge: str) -> Qt.CursorShape:
    """Get appropriate cursor for each resize edge."""
    cursors = {
        "left": Qt.CursorShape.SizeHorCursor,
        "right": Qt.CursorShape.SizeHorCursor,
        "top": Qt.CursorShape.SizeVerCursor,
        "bottom": Qt.CursorShape.SizeVerCursor,
        "top_left": Qt.CursorShape.SizeFDiagCursor,
        "top_right": Qt.CursorShape.SizeBDiagCursor,
        "bottom_left": Qt.CursorShape.SizeBDiagCursor,
        "bottom_right": Qt.CursorShape.SizeFDiagCursor,
    }
    return cursors.get(edge, Qt.CursorShape.ArrowCursor)


def update_resize_handles_geometry(main_window: "HollowSteamApp", handles: Dict[str, ResizeHandle]) -> None:
    """Calculate and set geometry for all resize handles."""
    if not handles:
        return

    w, h = main_window.width(), main_window.height()
    hw = 6

    geometries = {
        "top_left": (0, 0, hw, hw),
        "top_right": (w - hw, 0, hw, hw),
        "bottom_left": (0, h - hw, hw, hw),
        "bottom_right": (w - hw, h - hw, hw, hw),
        "left": (0, hw, hw, h - 2 * hw),
        "right": (w - hw, hw, hw, h - 2 * hw),
        "top": (hw, 0, w - 2 * hw, hw),
        "bottom": (hw, h - hw, w - 2 * hw, hw),
    }

    for name, geom in geometries.items():
        if name in handles:
            handles[name].setGeometry(*geom)
