"""Configure method for indexes namespace."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, cast

import orjson

from pinecone._internal.constants import INDEXES_API_VERSION
from pinecone._internal.logging import get_logger
from pinecone._internal.validation import require_non_empty


if TYPE_CHECKING:
    from pinecone.__interface__.indexes import IndexInfoProtocol


logger = get_logger(__name__)


def configure(
    self: Any,
    name: str,
    *,
    deletion_protection: str | None = None,
    tags: dict[str, str] | None = None,
    spec: dict[str, Any] | None = None,
    embed: dict[str, Any] | None = None,
) -> IndexInfoProtocol:
    """Update index configuration.

    Args:
        name: Index name to configure
        deletion_protection: Set to "enabled" or "disabled"
        tags: Update tags (set value to "" to delete a tag)
        spec: Update spec configuration:
            - Pod: {"pod": {"replicas": 4, "pod_type": "p1.x2"}}
            - Serverless: {"serverless": {"read_capacity": {...}}}
        embed: Update embedding configuration:
            - {"field_map": {...}, "read_parameters": {...}, "write_parameters": {...}}
            - Note: model cannot be changed once set

    Returns:
        Updated IndexInfo

    Raises:
        NotFoundError: If index does not exist
        BadRequestError: If configuration is invalid
        APIError: If the API returns an error response
        APIConnectionError: If the request fails to connect
        TimeoutError: If the request times out

    Example:
        >>> # Update deletion protection
        >>> pc.indexes.configure("my-index", deletion_protection="enabled")

    Example scaling pod replicas:
        >>> # Scale pod replicas
        >>> pc.indexes.configure("my-index", spec={"pod": {"replicas": 4}})

    Example with dedicated read nodes:
        >>> # Update serverless read capacity (dedicated nodes)
        >>> pc.indexes.configure(
        ...     "my-index",
        ...     spec={
        ...         "serverless": {
        ...             "read_capacity": {
        ...                 "mode": "Dedicated",
        ...                 "dedicated": {
        ...                     "node_type": "b1",
        ...                     "scaling": "Manual",
        ...                     "manual": {"shards": 2, "replicas": 2},
        ...                 },
        ...             }
        ...         }
        ...     },
        ... )
    """
    # 1. Validate inputs
    require_non_empty("name", name)

    # Validate at least one parameter is provided
    if deletion_protection is None and not tags and spec is None and embed is None:
        raise ValueError(
            "At least one configuration parameter must be provided: "
            "deletion_protection, tags, spec, or embed"
        )

    # Validate tags if provided
    if tags:
        for key, value in tags.items():
            if len(key) > 80:
                raise ValueError(f"Tag key '{key}' exceeds 80 character limit ({len(key)} chars)")
            if len(value) > 120:
                raise ValueError(
                    f"Tag value for key '{key}' exceeds 120 character limit ({len(value)} chars)"
                )

    # 2. Log operation start
    logger.info("Configuring index", name=name)

    # 3. Build request body
    request_body: dict[str, Any] = {}

    if deletion_protection is not None:
        request_body["deletion_protection"] = deletion_protection

    if tags:
        request_body["tags"] = tags

    if spec is not None:
        request_body["spec"] = spec

    if embed is not None:
        request_body["embed"] = embed

    try:
        # 4. Make HTTP request
        response = self._http.patch(
            f"{self._base_url}/indexes/{name}",
            content=orjson.dumps(request_body),
            headers={
                "Content-Type": "application/json",
                "X-Pinecone-Api-Version": INDEXES_API_VERSION,
            },
        )

        # 5. Transform response via adapter
        data = orjson.loads(response.content)
        result = self._adapter.to_index_model(data)

        # 6. Log success
        logger.debug("Index configured successfully", name=name)

        return cast("IndexInfoProtocol", result)

    except Exception:
        # 7. Log failure with context
        logger.exception("Failed to configure index", name=name)
        raise
