"""Rerank method for inference namespace."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from pinecone._internal.logging import get_logger
from pinecone._internal.validation import require_in_range, require_non_empty
from pinecone.models.inference import RerankDocument, RerankRequest, RerankResponse


if TYPE_CHECKING:
    from pinecone.__interface__.inference import RerankResponseProtocol


logger = get_logger(__name__)


def rerank(
    self: Any,
    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 a query.

    This method demonstrates handling of more complex request parameters
    and transforming string documents to structured request models.

    Args:
        model: Name of the reranking model (e.g., "bge-reranker-v2-m3")
        query: Query text to rank documents against
        documents: List of document texts to rerank (non-empty)
        top_n: Optional number of top results to return
        return_documents: Whether to include document text in results
        parameters: Optional model-specific parameters as a dict. Parameters
            are entirely model-specific - consult model documentation.
        timeout: Optional request timeout in seconds

    Returns:
        RerankResponse containing:
            - results: List of RerankResult with index, score, document
            - model: Name of the model used
            - usage: Token usage information

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

    Example:
        >>> response = inference.rerank(
        ...     model="bge-reranker-v2-m3",
        ...     query="What is machine learning?",
        ...     documents=[
        ...         "Machine learning is a subset of artificial intelligence",
        ...         "Python is a programming language",
        ...         "Deep learning uses neural networks",
        ...     ],
        ...     top_n=2,
        ... )
        >>> for result in response.results:
        ...     print(f"Document {result.index}: score {result.score:.3f}")

    Example with return_documents:
        >>> response = inference.rerank(
        ...     model="bge-reranker-v2-m3",
        ...     query="AI applications",
        ...     documents=["Text about AI", "Text about cooking"],
        ...     top_n=1,
        ...     return_documents=True,
        ... )
        >>> top_result = response.results[0]
        >>> print(f"Top document: {top_result.document}")

    Example with timeout:
        >>> try:
        ...     response = inference.rerank(
        ...         model="bge-reranker-v2-m3",
        ...         query="What is AI?",
        ...         documents=["AI is...", "ML is..."],
        ...         timeout=5.0,
        ...     )
        ... except TimeoutError:
        ...     print("Request timed out after 5 seconds")
    """
    # Validation
    require_non_empty("model", model)
    require_non_empty("query", query)
    require_non_empty("documents", documents)

    if top_n is not None:
        require_in_range("top_n", top_n, 1, len(documents))

    logger.info(
        "Reranking documents",
        model=model,
        document_count=len(documents),
        top_n=top_n,
        return_documents=return_documents,
        has_parameters=parameters is not None,
    )

    # Transform documents to structured format
    doc_objects: list[RerankDocument] = [RerankDocument(text=doc) for doc in documents]

    # Build request
    request: RerankRequest = RerankRequest(
        model=model,
        query=query,
        documents=doc_objects,
        top_n=top_n,
        return_documents=return_documents,
        parameters=parameters,
    )

    # Make HTTP request
    data: dict[str, Any] = self._make_inference_request("rerank", request, timeout)

    # Transform response via adapter
    result: RerankResponse = self._adapter.to_rerank_response(data)

    logger.debug(
        "Documents reranked successfully",
        model=result.model,
        result_count=len(result.results),
        total_tokens=result.usage.total_tokens,
    )

    return result
