"""Create method for async_backups namespace."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import msgspec
import orjson

from pinecone._internal.logging import get_logger
from pinecone._internal.validation import require_non_empty
from pinecone.models.backups import CreateBackupRequest


if TYPE_CHECKING:
    from pinecone.__interface__.backups import BackupInfoProtocol

logger = get_logger(__name__)


async def create(
    self: Any,
    index_name: str,
    *,
    name: str | None = None,
    description: str | None = None,
    timeout: float | None = None,
) -> BackupInfoProtocol:
    """Create a backup from a serverless index asynchronously.

    This operation creates a static copy of a serverless index that only consumes
    storage. The backup is non-queryable but can be used to restore an index later.

    Args:
        index_name: Name of the serverless index to back up.
        name: Optional user-defined display name for the backup. If not provided,
            a system-generated name will be used. Note: This is NOT the backup_id
            used to reference the backup. The backup_id is auto-generated and
            returned in the response.
        description: Optional description providing context for the backup.
        timeout: Optional timeout in seconds for the API request (not the backup
            creation itself, which happens asynchronously).

    Returns:
        BackupInfoProtocol with backup metadata including backup_id and status.
        The status will initially be "Initializing" as the backup happens
        asynchronously.

    Raises:
        ValueError: If index_name is empty or timeout is not positive.
        NotFoundError: If index not found.
        APIError: If backup creation fails.

    Example:
        >>> backup = await pc.backups.create(
        ...     index_name="my-index",
        ...     name="example-backup",
        ...     description="Monthly backup of production index",
        ... )
        >>> print(f"Backup ID: {backup.backup_id}")
        >>> print(f"Status: {backup.status}")
        >>>
        >>> # Poll until ready
        >>> import asyncio
        >>> while True:
        ...     info = await pc.backups.describe(backup.backup_id)
        ...     if info.status == "Ready":
        ...         break
        ...     await asyncio.sleep(10)
    """
    # Validate inputs
    require_non_empty("index_name", index_name)
    if timeout is not None and timeout <= 0:
        raise ValueError(f"timeout must be a positive number, received: {timeout}")

    logger.info(
        "Creating backup",
        index_name=index_name,
        backup_name=name,
        has_description=description is not None,
        timeout=timeout,
    )

    try:
        # Build request body - only include fields if provided
        if name is not None or description is not None:
            request = CreateBackupRequest(name=name, description=description)
            content = msgspec.json.encode(request)
        else:
            # Empty body for no optional params
            content = b"{}"

        # Make HTTP request
        response = await self._http.post(
            f"{self._base_url}/indexes/{index_name}/backups",
            content=content,
            headers={**self._headers, "Content-Type": "application/json"},
            timeout=timeout,
        )

        # Parse response (201 Created)
        data = orjson.loads(response.content)
        result: BackupInfoProtocol = self._adapter.to_backup_model(data)

        logger.info(
            "Backup created successfully",
            backup_id=result.backup_id,
            index_name=index_name,
            status=result.status,
        )

        return result  # noqa: TRY300

    except Exception:
        logger.exception("Failed to create backup", index_name=index_name, backup_name=name)
        raise
