"""Embedding protocol and adapter for sagellm.

This module is the canonical embedding interface in sagellm.
"""

from __future__ import annotations

import inspect
from typing import Any, Protocol, runtime_checkable


@runtime_checkable
class EmbeddingProtocol(Protocol):
    """Standard embedding interface used across sagellm ecosystem."""

    def embed(self, texts: list[str], model: str | None = None) -> list[list[float]]:
        """Embed a batch of texts."""

    def get_dim(self) -> int:
        """Return embedding vector dimension."""


class EmbeddingClientAdapter:
    """Adapt single-text embedders to `EmbeddingProtocol`."""

    def __init__(self, embedder: Any):
        self._embedder = embedder

    def embed(self, texts: list[str], model: str | None = None) -> list[list[float]]:
        if hasattr(self._embedder, "embed_batch"):
            return self._embedder.embed_batch(texts)
        return [self._embedder.embed(text) for text in texts]

    def get_dim(self) -> int:
        return self._embedder.get_dim()


def adapt_embedding_client(embedder: Any) -> EmbeddingProtocol:
    """Adapt arbitrary embedder into `EmbeddingProtocol`."""
    if not hasattr(embedder, "embed") or not hasattr(embedder, "get_dim"):
        raise TypeError(
            f"Cannot adapt {type(embedder).__name__} to EmbeddingProtocol. "
            "Missing 'embed' or 'get_dim' method."
        )

    sig = inspect.signature(embedder.embed)
    params = list(sig.parameters.keys())
    if "texts" in params:
        return embedder
    return EmbeddingClientAdapter(embedder)
