from __future__ import annotations

from typing import Any

from external_connector.providers.base import ConnectorProvider


class CompositeProvider:
    provider_id = "composite"

    def __init__(self, providers: list[ConnectorProvider]) -> None:
        self.providers = providers
        self._by_kind: dict[str, ConnectorProvider] = {}
        for provider in providers:
            for connector in provider.connectors():
                self._by_kind[str(connector["kind"])] = provider

    def connectors(self) -> list[dict[str, Any]]:
        items: list[dict[str, Any]] = []
        for provider in self.providers:
            items.extend(provider.connectors())
        return items

    def health(self) -> dict[str, Any]:
        return {"ok": True, "providerId": self.provider_id, "providers": [provider.health() for provider in self.providers]}

    def start_session(self, payload: dict[str, Any]) -> dict[str, Any]:
        return self._provider(str(payload["kind"])).start_session(payload)

    def get_session(self, session_id: str) -> dict[str, Any]:
        for provider in self.providers:
            try:
                return provider.get_session(session_id)
            except KeyError:
                continue
        raise KeyError(session_id)

    def cancel_session(self, session_id: str) -> None:
        for provider in self.providers:
            try:
                provider.cancel_session(session_id)
                return None
            except KeyError:
                continue
        raise KeyError(session_id)

    def logout(self, connection_id: str) -> None:
        for provider in self.providers:
            provider.logout(connection_id)
        return None

    def send(self, payload: dict[str, Any]) -> dict[str, Any]:
        return self._provider(str(payload["kind"])).send(payload)

    def handle_event(self, payload: dict[str, Any]) -> dict[str, Any]:
        for provider in self.providers:
            handler = getattr(provider, "handle_event", None)
            if handler is None:
                continue
            try:
                return dict(handler(payload))
            except KeyError:
                continue
        raise KeyError("No event provider matched")

    def _provider(self, kind: str) -> ConnectorProvider:
        provider = self._by_kind.get(kind)
        if provider is None:
            raise KeyError(f"Unsupported connector kind: {kind}")
        return provider
