"""Channel manager: registers and manages messaging channels."""

from __future__ import annotations

import logging
from collections.abc import Callable

from agntspace.channels.base import Channel

log = logging.getLogger(__name__)


class ChannelManager:
    """Manages all connected messaging channels."""

    def __init__(self) -> None:
        self._channels: dict[str, Channel] = {}
        self._message_handler: Callable | None = None

    def register(self, channel: Channel) -> None:
        """Register a channel."""
        self._channels[channel.name] = channel
        if self._message_handler:
            channel.on_message(self._message_handler)
        log.debug("Channel registered: %s", channel.name)

    def set_message_handler(self, handler: Callable) -> None:
        """Set the callback for incoming messages across all channels."""
        self._message_handler = handler
        for channel in self._channels.values():
            channel.on_message(handler)

    async def connect_all(self) -> None:
        """Connect all registered channels."""
        for name, channel in self._channels.items():
            try:
                await channel.connect()
                log.info("Channel connected: %s", name)
            except Exception:
                log.exception("Failed to connect channel: %s", name)

    async def disconnect_all(self) -> None:
        """Disconnect all channels."""
        for name, channel in self._channels.items():
            try:
                await channel.disconnect()
            except Exception:
                log.exception("Failed to disconnect channel: %s", name)

    async def broadcast(self, text: str) -> None:
        """Send a notification to all connected channels."""
        for channel in self._channels.values():
            if channel.is_connected and hasattr(channel, "_chat_id") and channel._chat_id:
                try:
                    await channel.send_notification(channel._chat_id, text)
                except Exception:
                    log.debug("Broadcast failed for %s", channel.name)

    def get_channel(self, name: str) -> Channel | None:
        return self._channels.get(name)

    def list_channels(self) -> list[dict]:
        """List all channels with status."""
        return [
            {
                "name": ch.name,
                "connected": ch.is_connected,
            }
            for ch in self._channels.values()
        ]

    @property
    def connected_count(self) -> int:
        return sum(1 for ch in self._channels.values() if ch.is_connected)
