"""Async inference namespace implementation for embeddings and reranking.

This module provides the async implementation for the Inference API, enabling
concurrent embedding and reranking operations for agent workflows and async frameworks.
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from pinecone.__interface__.inference import AsyncInferenceNamespaceProtocol
from pinecone._internal.adapters.inference_adapter import InferenceAdapter
from pinecone._internal.introspection import InteractiveIntrospectionMixin


if TYPE_CHECKING:
    from pinecone._internal.http import AsyncHTTPClient


class AsyncInference(InteractiveIntrospectionMixin, AsyncInferenceNamespaceProtocol):
    """Async implementation of inference operations for embeddings and reranking.

    This class enables concurrent API calls for embedding and reranking, making it
    ideal for agent workflows that need to process multiple documents in parallel or
    integrate with async frameworks like FastAPI.

    Args:
        http_client: Async HTTP client for making API requests
        base_url: Base URL for the Inference API

    Example:
        >>> from pinecone import AsyncPinecone
        >>> import asyncio
        >>>
        >>> async def main():
        ...     async with AsyncPinecone(api_key="...") as pc:
        ...         # Generate embeddings
        ...         response = await pc.inference.embed(
        ...             model="multilingual-e5-large",
        ...             texts=["Hello world", "Goodbye world"],
        ...             parameters={"input_type": "passage", "truncate": "END"},
        ...         )
        ...         embeddings = response.embeddings
        ...
        ...         # Rerank documents
        ...         response = await pc.inference.rerank(
        ...             model="bge-reranker-v2-m3",
        ...             query="What is machine learning?",
        ...             documents=["ML is a subset of AI", "Python is a language"],
        ...             top_n=1,
        ...         )
        ...         top_doc = response.results[0]
        >>>
        >>> asyncio.run(main())

    Example with concurrent operations:
        >>> async def embed_batches(pc, text_batches):
        ...     tasks = [
        ...         pc.inference.embed(model="multilingual-e5-large", texts=batch)
        ...         for batch in text_batches
        ...     ]
        ...     return await asyncio.gather(*tasks)
    """

    def __init__(
        self,
        http_client: AsyncHTTPClient,
        base_url: str = "https://api.pinecone.io",
    ):
        """Initialize async Inference namespace.

        Args:
            http_client: Async HTTP client for making API requests
            base_url: Base URL for the Inference API. Defaults to production endpoint.
        """
        self._http = http_client
        self._base_url = base_url
        self._adapter = InferenceAdapter()

        # Import and bind methods once at initialization (eager binding)
        from pinecone.async_inference import (  # noqa: PLC0415
            _embed,
            _helpers,
            _list_models,
            _rerank,
        )

        self._make_inference_request = _helpers._make_inference_request.__get__(self, type(self))
        self.list_models = _list_models.list_models.__get__(self, type(self))  # type: ignore[method-assign]
        self.embed = _embed.embed.__get__(self, type(self))  # type: ignore[method-assign]
        self.rerank = _rerank.rerank.__get__(self, type(self))  # type: ignore[method-assign]

    def __repr__(self) -> str:
        """Return string representation of async inference namespace."""
        return f"AsyncInference(base_url='{self._base_url}')"
