"""Async inference namespace protocol."""

from typing import Any, Protocol, runtime_checkable

from pinecone.__interface__.inference.responses import (
    EmbeddingResponseProtocol,
    ListModelsResponseProtocol,
    RerankResponseProtocol,
)


@runtime_checkable
class AsyncInferenceNamespaceProtocol(Protocol):
    """Protocol for async inference operations (embeddings and reranking).

    Example:
        >>> from pinecone import AsyncPinecone
        >>> import asyncio
        >>>
        >>> async def main():
        ...     async with AsyncPinecone(api_key="...") as pc:
        ...         # List available models
        ...         response = await pc.inference.list_models()
        ...         for model in response.models:
        ...             print(f"{model.model}: {model.type}")
        ...         # Generate embeddings
        ...         response = await pc.inference.embed(
        ...             model="multilingual-e5-large", texts=["Hello", "World"]
        ...         )
        ...         # Rerank documents
        ...         response = await pc.inference.rerank(
        ...             model="bge-reranker-v2-m3",
        ...             query="What is AI?",
        ...             documents=["AI is...", "ML is..."],
        ...         )
        >>>
        >>> asyncio.run(main())
    """

    async def list_models(
        self,
        *,
        model_type: str | None = None,
        vector_type: str | None = None,
        timeout: float | None = None,
    ) -> ListModelsResponseProtocol:
        """List available embedding and reranking models asynchronously.

        Args:
            model_type: Optional filter by model type ('embed' or 'rerank')
            vector_type: Optional filter by vector type ('dense' or 'sparse') for embedding models
            timeout: Optional request timeout in seconds

        Returns:
            ListModelsResponse containing:
                - models: List of ModelInfo objects with model details

        Raises:
            APIError: If the API returns an error response
            APIConnectionError: If the request fails to connect
            TimeoutError: If the request times out

        Example:
            >>> async with AsyncPinecone(api_key="...") as pc:
            ...     response = await pc.inference.list_models()
            ...     for model in response.models:
            ...         print(f"{model.model} ({model.type}): {model.short_description}")

        Example with filters:
            >>> async with AsyncPinecone(api_key="...") as pc:
            ...     # List only embedding models
            ...     response = await pc.inference.list_models(model_type="embed")
            ...     # List only sparse embedding models
            ...     response = await pc.inference.list_models(model_type="embed", vector_type="sparse")
        """
        ...

    async def embed(
        self,
        model: str,
        *,
        texts: list[str],
        parameters: dict[str, Any] | None = None,
        timeout: float | None = None,
    ) -> EmbeddingResponseProtocol:
        """Generate embeddings for texts asynchronously.

        Args:
            model: Model name to use.
            texts: List of texts to embed.
            parameters: Optional model-specific parameters.
            timeout: Optional request timeout in seconds.

        Returns:
            EmbeddingResponse with generated embeddings.

        Example:
            >>> async with AsyncPinecone(api_key="...") as pc:
            ...     response = await pc.inference.embed(
            ...         model="multilingual-e5-large", texts=["Hello world", "Goodbye world"]
            ...     )
            ...     embeddings = response.embeddings
        """
        ...

    async def rerank(
        self,
        model: str,
        *,
        query: str,
        documents: list[str],
        top_n: int | None = None,
        return_documents: bool = False,
        parameters: dict[str, Any] | None = None,
        timeout: float | None = None,
    ) -> RerankResponseProtocol:
        """Rerank documents by relevance to query asynchronously.

        Args:
            model: Model name to use.
            query: Query text.
            documents: List of documents to rerank.
            top_n: Optional number of top results to return.
            return_documents: Whether to include document text in results.
            parameters: Optional model-specific parameters.
            timeout: Optional request timeout in seconds.

        Returns:
            RerankResponse with reranked results.

        Example:
            >>> async with AsyncPinecone(api_key="...") as pc:
            ...     response = await pc.inference.rerank(
            ...         model="bge-reranker-v2-m3",
            ...         query="What is machine learning?",
            ...         documents=[
            ...             "Machine learning is a subset of AI",
            ...             "Deep learning uses neural networks",
            ...             "Python is a programming language",
            ...         ],
            ...         top_n=2,
            ...     )
            ...     for result in response.results:
            ...         print(f"Doc {result.index}: {result.score}")
        """
        ...
