"""Helper functions for async inference namespace."""

from __future__ import annotations

import asyncio

from typing import TYPE_CHECKING, Any, cast

import msgspec
import orjson

from pinecone._internal.constants import INFERENCE_API_VERSION
from pinecone._internal.logging import get_logger
from pinecone.exceptions import APIConnectionError, APIError


if TYPE_CHECKING:
    from pinecone.models.inference import EmbedRequest, RerankRequest


logger = get_logger(__name__)


async def _make_inference_request(
    self: Any,
    endpoint: str,
    request: EmbedRequest | RerankRequest | None = None,
    timeout: float | None = None,
    params: dict[str, str] | None = None,
) -> dict[str, Any]:
    """Make async HTTP request to inference API with standard headers.

    Args:
        endpoint: API endpoint (e.g., "embed", "rerank", "models")
        request: Optional request model to serialize (for POST requests)
        timeout: Optional request timeout in seconds
        params: Optional query parameters (for GET requests)

    Returns:
        Parsed JSON response as dictionary

    Raises:
        APIError: If the API returns an error response
        ConnectionError: If the request fails to connect
        TimeoutError: If the request times out
        asyncio.CancelledError: If the operation is cancelled
    """
    try:
        headers = {
            "X-Pinecone-Api-Version": INFERENCE_API_VERSION,
        }

        kwargs: dict[str, Any] = {"headers": headers}

        if timeout is not None:
            kwargs["timeout"] = timeout

        if request is not None:
            # POST request with body
            headers["Content-Type"] = "application/json"
            kwargs["content"] = msgspec.json.encode(request)
            response = await self._http.post(f"{self._base_url}/{endpoint}", **kwargs)
        else:
            # GET request with query params
            if params:
                kwargs["params"] = params
            response = await self._http.get(f"{self._base_url}/{endpoint}", **kwargs)

        return cast("dict[str, Any]", orjson.loads(response.content))
    except asyncio.CancelledError:
        logger.debug("Request cancelled", endpoint=endpoint)
        raise
    except APIConnectionError as e:
        # Network/connection errors - preserve type with added context
        raise APIConnectionError(f"Inference {endpoint} request failed: {e.message}") from e
    except APIError as e:
        # API errors - recreate with same attributes and added context
        raise APIError(
            f"Inference {endpoint} request failed: {e.message}",
            status_code=e.status_code,
            response_body=e.response_body,
        ) from e
