"""Platform-agnostic hotkey manager interface + dispatcher."""

from __future__ import annotations

import sys
from abc import ABC, abstractmethod
from collections.abc import Callable


class HotkeyManager(ABC):
    """Abstract hotkey manager — register global keyboard shortcuts."""

    @abstractmethod
    def register(self, hotkey: str, callback: Callable[[], None]) -> bool:
        """Register *hotkey* (e.g. 'ctrl+shift+space') to call *callback*.

        Returns True on success.
        """

    @abstractmethod
    def unregister(self, hotkey: str) -> bool:
        """Unregister a previously registered hotkey.

        Returns True on success.
        """

    @abstractmethod
    def start(self) -> None:
        """Start listening for hotkeys (may start a background thread)."""

    @abstractmethod
    def stop(self) -> None:
        """Stop listening and clean up resources."""

    def update_hotkey(
        self,
        old_hotkey: str,
        new_hotkey: str,
        callback: Callable[[], None],
    ) -> bool:
        """Atomically unregister *old_hotkey* and register *new_hotkey*.

        Returns True if the new hotkey was registered successfully.
        If old_hotkey equals new_hotkey the existing registration is
        re-registered with the supplied callback.
        """
        self.unregister(old_hotkey)
        return self.register(new_hotkey, callback)


def get_hotkey_manager(stealth: bool = False) -> HotkeyManager:
    """Return the platform-specific hotkey manager.

    Args:
        stealth: When True on Windows, use GetAsyncKeyState polling instead
                 of RegisterHotKey. Polling works even when keyboard hooks
                 (e.g. exam proctoring software) swallow WM_HOTKEY messages.
    """
    if sys.platform == "win32":
        # Always use polling on Windows — works both with and without CSCA.
        # RegisterHotKey fails when CSCA hooks swallow WM_HOTKEY messages,
        # and since MuraveyChina starts BEFORE CSCA, we can't predict at
        # startup whether CSCA will be running later.
        from .impl_win_polling import PollingHotkeyManager

        return PollingHotkeyManager()
    elif sys.platform == "darwin":
        from .impl_mac import MacHotkeyManager

        return MacHotkeyManager()
    else:
        raise RuntimeError(f"Unsupported platform: {sys.platform}")
