"""Unified adapter that hides backend differences from callers."""

from __future__ import annotations

from collections.abc import AsyncIterator
from typing import TYPE_CHECKING, Any

from thryve.core.backends.factory import BackendFactory
from thryve.core.backends.param import BaseBackendParam

if TYPE_CHECKING:
    from thryve.core.context.models import BackendInfo, ChatResponse, Message
    from thryve.core.tools.models import Tool


class BackendAdapter:
    """Public-facing adapter around any :class:`BaseBackend`.

    Callers interact exclusively with this class; they never need to know
    which concrete backend is running underneath.
    """

    def __init__(
        self,
        backend_type: str,
        config: dict[str, Any] | BaseBackendParam,
    ) -> None:
        self._backend = BackendFactory.create(backend_type, config)

    # -- Generation -----------------------------------------------------

    def generate(self, messages: list[Message], **kwargs: Any) -> ChatResponse:
        return self._backend.generate(messages, **kwargs)

    async def generate_async(self, messages: list[Message], **kwargs: Any) -> ChatResponse:
        return await self._backend.generate_async(messages, **kwargs)

    async def generate_stream(self, messages: list[Message], **kwargs: Any) -> AsyncIterator[str]:
        async for chunk in self._backend.generate_stream(messages, **kwargs):
            yield chunk

    # -- Embeddings -----------------------------------------------------

    def embeddings(self, texts: list[str], **kwargs: Any) -> list[list[float]]:
        return self._backend.embeddings(texts, **kwargs)

    # -- Tool binding ---------------------------------------------------

    def bind_tools(self, tools: list[Tool]) -> BackendAdapter:
        """Return a **new** adapter with tools bound."""
        adapter = BackendAdapter.__new__(BackendAdapter)
        adapter._backend = self._backend.bind_tools(tools)
        return adapter

    # -- Introspection --------------------------------------------------

    def get_info(self) -> BackendInfo:
        return self._backend.get_info()
