"""
Secure event handler registry.

Replaces dangerous eval() pattern with explicit handler registration.
"""

from typing import Callable, Dict, Any
import logging

logger = logging.getLogger(__name__)


class InvalidEventError(Exception):
    """Raised when attempting to call invalid or unregistered event"""
    pass


class EventHandlerRegistry:
    """
    Registry for secure event handler dispatch.

    Usage:
        registry = EventHandlerRegistry()
        registry.register("characterSetup", characterSetup)
        result = registry.call("characterSetup", player, "answer", key, message)
    """

    def __init__(self):
        self._handlers: Dict[str, Callable] = {}

    def register(self, event_type: str, handler: Callable) -> None:
        """Register an event handler function"""
        if not event_type or not isinstance(event_type, str):
            raise ValueError(f"Invalid event type: {event_type}")

        if not callable(handler):
            raise ValueError(f"Handler must be callable: {handler}")

        # Prevent registration of dangerous patterns
        if "__" in event_type or event_type.startswith("_"):
            raise ValueError(f"Event type cannot contain __ or start with _: {event_type}")

        # Skip if already registered (prevents duplicate warnings during hot-reload)
        if event_type in self._handlers:
            logger.debug(f"Event handler {event_type} already registered, skipping duplicate registration")
            return

        self._handlers[event_type] = handler
        logger.debug(f"Registered event handler: {event_type}")

    def call(self, event_type: str, player: Any, mode: str, key: Any, message: Any) -> Any:
        """
        Safely call a registered event handler.

        Args:
            event_type: The event type to dispatch
            player: Player object
            mode: Mode string (usually "answer")
            key: Event key
            message: Event message

        Returns:
            Result from handler function

        Raises:
            InvalidEventError: If event type is not registered or invalid
        """
        # Validate event type
        if not event_type or not isinstance(event_type, str):
            raise InvalidEventError(f"Invalid event type: {event_type}")

        # Prevent dangerous patterns
        if "__" in event_type or event_type.startswith("_"):
            raise InvalidEventError(f"Dangerous event type rejected: {event_type}")

        # Get handler
        handler = self._handlers.get(event_type)
        if handler is None:
            raise InvalidEventError(f"No handler registered for event: {event_type}")

        # Call handler safely
        try:
            return handler(player, mode, key, message)
        except Exception as e:
            logger.error(f"Error calling handler {event_type}: {e}", exc_info=True)
            raise

    def is_registered(self, event_type: str) -> bool:
        """Check if an event type is registered"""
        return event_type in self._handlers

    def list_events(self) -> list[str]:
        """List all registered event types"""
        return list(self._handlers.keys())


# Global registry instance
_registry = EventHandlerRegistry()


def register_event_handler(event_type: str, handler: Callable) -> None:
    """Register an event handler in the global registry"""
    _registry.register(event_type, handler)


def call_event_handler(event_type: str, player: Any, mode: str, key: Any, message: Any) -> Any:
    """Call an event handler from the global registry"""
    return _registry.call(event_type, player, mode, key, message)


def is_event_registered(event_type: str) -> bool:
    """Check if an event is registered in the global registry"""
    return _registry.is_registered(event_type)
