# -*- coding: utf-8 -*-
# gui/components/model_view/_scenario_custom_handler.py
"""Универсальный сценарий с инжектированными обработчиками.

Покрывает режимы, использующие сценарный push/pop в InteractionManager:
- rack_placement (размещение стеллажей)
- rack_select (выбор стеллажа в зоне)
- shelf_placement (размещение полок)
- measure (режим измерений)
- origin_point (выбор точки привязки)

Каждый экземпляр получает уникальное имя и набор обработчиков.
"""

from __future__ import annotations

import math
from typing import TYPE_CHECKING, Callable, Optional

from PySide6.QtCore import Qt

from gui.components.model_view._interaction_scenario import (
    CameraPolicy,
    InteractionScenario,
)
from error_logger import log_exception

if TYPE_CHECKING:  # pragma: no cover
    from gui.components.model_view_widget import ModelViewWidget


class CustomHandlerScenario(InteractionScenario):
    """Сценарий с инжектированными hover/click обработчиками и горячими клавишами."""

    def __init__(
        self,
        name: str,
        *,
        camera_policy: CameraPolicy = CameraPolicy.FREE,
        click_handler: Optional[Callable] = None,
        hover_handler: Optional[Callable] = None,
        hover_screen_handler: Optional[Callable] = None,
        hotkeys: Optional[dict[int, Callable]] = None,
        on_activate_fn: Optional[Callable] = None,
        on_deactivate_fn: Optional[Callable] = None,
    ) -> None:
        self.name = name
        self.camera_policy = camera_policy
        self._click_handler = click_handler
        self._hover_handler = hover_handler
        self._hover_screen_handler = hover_screen_handler
        self._hotkeys: dict[int, Callable] = hotkeys or {}
        self._on_activate_fn = on_activate_fn
        self._on_deactivate_fn = on_deactivate_fn

    def on_activate(self, mv: "ModelViewWidget") -> None:
        # Установить обработчики в mv
        if self._click_handler is not None:
            mv._custom_click_handler = self._click_handler
        if self._hover_handler is not None:
            mv._hover_handler = self._hover_handler
        if self._hover_screen_handler is not None:
            mv._hover_screen_handler = self._hover_screen_handler
        if self._on_activate_fn:
            self._on_activate_fn(mv)

    def on_deactivate(self, mv: "ModelViewWidget") -> None:
        if self._on_deactivate_fn:
            self._on_deactivate_fn(mv)
        # Очищаем обработчики, если они были установлены нами
        if self._click_handler is not None:
            if mv._custom_click_handler is self._click_handler:
                mv._custom_click_handler = None
        if mv._hover_handler is self._hover_handler:
            mv._hover_handler = None
        if mv._hover_screen_handler is self._hover_screen_handler:
            mv._hover_screen_handler = None

    def on_hover(self, mv: "ModelViewWidget", event) -> None:
        """Вызов инжектированных hover-обработчиков."""
        try:
            if self._hover_screen_handler is not None:
                self._hover_screen_handler(event.position().x(), event.position().y())

            if self._hover_handler is not None:
                pos = mv._plotter.pick_mouse_position() if mv._plotter else None
                if pos is None and mv._plotter and mv._plotter.picker and mv._plotter.renderer:
                    try:
                        sx, sy = mv._event_to_vtk_display_xy(event)
                        mv._plotter.picker.Pick(sx, sy, 0, mv._plotter.renderer)
                        pos = mv._plotter.picker.GetPickPosition()
                    except Exception as _exc:
                        pos = None
                if pos is not None:
                    x, y, z = pos[0], pos[1], pos[2]
                    if all(math.isfinite(v) for v in (x, y, z)):
                        mv._last_hover_point = (x, y, z)
                        self._hover_handler(x, y, z)
                elif mv._last_hover_point is not None:
                    self._hover_handler(*mv._last_hover_point)
        except Exception as _exc:
            log_exception(__name__, "on_hover", _exc)
    def on_key_press(self, mv: "ModelViewWidget", event) -> bool:
        handler = self._hotkeys.get(event.key())
        if handler is not None:
            try:
                result = handler()
                return bool(result) if result is not None else True
            except Exception as _exc:
                log_exception(__name__, "on_key_press", _exc)
            return True

        # Глобальный Esc fallback
        if event.key() == Qt.Key.Key_Escape:
            cancel = getattr(mv, "_global_cancel_handler", None)
            if callable(cancel):
                try:
                    cancel()
                except Exception as _exc:
                    log_exception(__name__, "on_key_press", _exc)
                return True
        return False
