"""QRP message router — dispatches incoming messages to handlers.

The router sits between the ConnectionManager and the execution engine.
It maps message types to async handler functions and validates basic
message structure before dispatching.
"""

from __future__ import annotations

import logging
from typing import Any, Callable, Coroutine

from qremotex.protocol.messages import MessageType

logger = logging.getLogger("qremotex.protocol")

Handler = Callable[[dict[str, Any]], Coroutine[Any, Any, None]]


class MessageRouter:
    """Dispatch incoming QRP messages to registered handlers."""

    def __init__(self) -> None:
        self._handlers: dict[str, Handler] = {}

    def register(self, msg_type: str | MessageType, handler: Handler) -> None:
        """Register a handler for a message type."""
        key = msg_type.value if isinstance(msg_type, MessageType) else msg_type
        self._handlers[key] = handler

    async def dispatch(self, msg: dict[str, Any]) -> None:
        """Route an incoming message to the registered handler."""
        msg_type = msg.get("type")
        if not msg_type:
            logger.warning("Received message without 'type' field")
            return

        handler = self._handlers.get(msg_type)
        if handler is None:
            logger.debug("No handler registered for message type: %s", msg_type)
            return

        try:
            await handler(msg)
        except Exception:
            logger.exception("Handler error for message type=%s", msg_type)
