"""Base class for all SDK response models.

Provides serialization and dictionary-style access for msgspec.Struct models.
"""

from __future__ import annotations

from typing import Any

import msgspec
import msgspec.json

from msgspec import Struct


class BaseModel(Struct):
    """Base class for all SDK response models.

    Provides two ways to work with model data:

    1. **Attribute access** (recommended):
       >>> model.field_name

    2. **Serialization** (convert to dict/JSON):
       >>> model.to_dict()  # Convert to Python dict
       >>> model.to_json()  # Convert to JSON string

    Examples:
        Basic usage with all three access patterns:

        >>> from pinecone.models._base import BaseModel
        >>>
        >>> class User(BaseModel, kw_only=True):
        ...     name: str
        ...     age: int
        ...     email: str | None = None
        >>>
        >>> user = User(name="Alice", age=30)
        >>>
        >>> # Attribute access
        >>> user.name
        'Alice'
        >>> user.age
        30
        >>>
        >>> # Serialization to dict
        >>> data = user.to_dict()
        >>> data["name"]
        'Alice'
        >>> "email" in data
        True
        >>>
        >>> # Serialization to JSON
        >>> user.to_json()
        '{"name":"Alice","age":30,"email":null}'

        Dynamic field access via to_dict():

        >>> field_name = "name"  # Dynamic field from config
        >>> user.to_dict()[field_name]
        'Alice'
        >>>
        >>> for key, value in user.to_dict().items():
        ...     print(f"{key}: {value}")
        name: Alice
        age: 30
        email: None
    """

    # ========== Serialization Methods ==========

    def to_dict(self) -> dict[str, Any]:
        """Convert model to Python dictionary.

        Recursively converts the model and all nested models to Python
        dictionaries using msgspec's fast to_builtins() conversion.

        Returns:
            Dictionary representation with all fields converted to Python
            primitives (dict, list, str, int, float, bool, None).

        Examples:
            Simple conversion:

            >>> response = pc.inference.embed(model="...", texts=["hello"])
            >>> data = response.to_dict()
            >>> print(data.keys())
            dict_keys(['data', 'model', 'usage', 'vector_type'])
            >>> print(data["model"])
            'multilingual-e5-large'

            Nested models are recursively converted:

            >>> index = pc.indexes.describe("my-index")
            >>> index_dict = index.to_dict()
            >>> print(index_dict["status"]["state"])
            'Ready'

            Use for integration with code expecting dicts:

            >>> import pandas as pd
            >>> results = [match.to_dict() for match in query_response.matches]
            >>> df = pd.DataFrame(results)
        """
        return msgspec.to_builtins(self)  # type: ignore[no-any-return]

    def to_json(self) -> str:
        """Convert model to JSON string.

        Serializes the model to a JSON string using msgspec's fast JSON
        encoder. The resulting string can be used for logging, saving to
        files, or sending to external systems.

        Returns:
            JSON string representation of the model.

        Examples:
            Save to file:

            >>> response = pc.inference.embed(model="...", texts=["hello"])
            >>> with open("response.json", "w") as f:
            ...     f.write(response.to_json())

            Use in logging:

            >>> import logging
            >>> logging.info(f"API response: {response.to_json()}")

            Send to external API:

            >>> import httpx
            >>> httpx.post(
            ...     "https://api.example.com/webhook",
            ...     content=response.to_json(),
            ...     headers={"Content-Type": "application/json"},
            ... )
        """
        return msgspec.json.encode(self).decode("utf-8")


__all__ = ["BaseModel"]
