"""Pluggable bridge layer — translates between the OpenAI HTTP protocol and
arbitrary agent-native transports (WebSocket, stdio, gRPC, …)."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any

BRIDGE_REGISTRY: dict[str, type[Bridge]] = {}


def register_bridge(name: str):
    """Class decorator that registers a :class:`Bridge` subclass."""

    def _decorator(cls: type[Bridge]) -> type[Bridge]:
        BRIDGE_REGISTRY[name] = cls
        return cls

    return _decorator


def _ensure_builtins_loaded() -> None:
    """Import all built-in bridge modules so their ``@register_bridge``
    decorators populate :data:`BRIDGE_REGISTRY`."""
    if _ensure_builtins_loaded._done:
        return
    _ensure_builtins_loaded._done = True

    import importlib
    import pathlib

    pkg_dir = pathlib.Path(__file__).parent
    for module_path in pkg_dir.glob("*.py"):
        name = module_path.stem
        if name.startswith("_"):
            continue
        try:
            importlib.import_module(f"deskclaw_client.bridges.{name}")
        except Exception:
            pass

_ensure_builtins_loaded._done = False  # type: ignore[attr-defined]


def get_bridge(name: str, **kwargs: Any) -> Bridge:
    """Instantiate a registered bridge by *name*."""
    _ensure_builtins_loaded()
    if name not in BRIDGE_REGISTRY:
        available = ", ".join(sorted(BRIDGE_REGISTRY)) or "(none)"
        raise ValueError(f"Unknown bridge {name!r}. Available: {available}")
    return BRIDGE_REGISTRY[name](**kwargs)


class Bridge(ABC):
    """Transport-agnostic bridge between the local HTTP proxy and a remote
    agent that speaks a non-HTTP protocol."""

    @abstractmethod
    async def connect(self) -> None:
        """Establish a connection to the agent backend."""

    @abstractmethod
    async def chat(
        self,
        messages: list[dict[str, Any]],
        *,
        model: str = "",
        temperature: float = 1.0,
        max_tokens: int | None = None,
        **kwargs: Any,
    ) -> dict[str, Any]:
        """Send a chat-completion request and return an OpenAI-shaped response
        dict (with at least ``choices[0].message.content``)."""

    @abstractmethod
    async def close(self) -> None:
        """Tear down the connection gracefully."""

    async def health(self) -> dict[str, Any]:
        """Optional liveness probe.  Override for richer health info."""
        return {"status": "ok"}
