"""Provider interface contracts for model layer clients.

Defines the base ``ProviderABC`` abstract base class that all model provider
clients (LiteLLM, Ollama, llama.cpp) must implement.  This ensures structural
and behavioral compatibility across providers.
"""

from __future__ import annotations

from abc import ABC, abstractmethod
from collections.abc import Iterator
from typing import Any, Protocol

ChatResult = str | Iterator[dict[str, Any]]
"""Result of a chat completion: either a plain string or a stream of chunks."""


class ProviderABC(ABC):
    """Abstract base class defining the contract for all model provider clients."""

    @abstractmethod
    def chat(
        self,
        model: str,
        messages: list[dict[str, str]],
        **kwargs: Any,
    ) -> ChatResult:
        """Send a chat completion request.

        Args:
            model: The model identifier to use.
            messages: The conversation messages.
            **kwargs: Additional provider-specific parameters.

        Returns:
            The model's response content as a string, or an iterator of
            response chunks when streaming is requested.
        """

    @abstractmethod
    def embed(
        self,
        model: str,
        texts: list[str],
        **kwargs: Any,
    ) -> list[list[float]]:
        """Create embeddings for the given texts.

        Args:
            model: The model identifier to use.
            texts: The texts to embed.
            **kwargs: Additional provider-specific parameters.

        Returns:
            A list of embedding vectors.
        """

    @abstractmethod
    def list_models(self) -> list[dict[str, Any]]:
        """List available models from the provider.

        Returns:
            A list of model info dictionaries.
        """

    @abstractmethod
    def is_available(self) -> bool:
        """Check if the provider is available/healthy.

        Returns:
            True if the provider is reachable and operational.
        """

    @abstractmethod
    def health_check(self) -> dict[str, Any]:
        """Perform a health check on the provider.

        Returns:
            A dictionary with health status information.
        """


class ProviderProtocol(Protocol):
    """Structural protocol for provider duck-typing verification."""

    def chat(
        self,
        model: str,
        messages: list[dict[str, str]],
        **kwargs: Any,
    ) -> ChatResult:
        ...

    def embed(
        self,
        model: str,
        texts: list[str],
        **kwargs: Any,
    ) -> list[list[float]]:
        ...

    def list_models(self) -> list[dict[str, Any]]:
        ...

    def is_available(self) -> bool:
        ...

    def health_check(self) -> dict[str, Any]:
        ...
