from __future__ import annotations

from typing import Generic, TypeVar

from pydantic import BaseModel

from ...exceptions import MissingDataError
from .base import APIDataModel


class Status(APIDataModel):
    """Response status metadata returned by the API."""

    code: int | None = None
    msg: str = ""
    request_id: str | None = None


T = TypeVar("T")


class APIEnvelope(BaseModel, Generic[T]):
    """Generic wrapper around every SeaArt API response.

    All resource methods return an ``APIEnvelope[T]`` (or its subclass
    ``AsyncTaskEnvelope[T]`` for generation tasks). The server always sends a
    ``status`` object; the ``data`` payload is present on success and ``None``
    for endpoints that return no body (typed as ``APIEnvelope[None]``).

    Example:
        >>> result = await client.account.me()
        >>> print(result.value.name)   # raises MissingDataError if data is None
        >>> print(result.data)         # None-safe alternative
        >>> print(result.status.code)  # raw API status code
    """

    status: Status
    data: T | None = None

    @property
    def value(self) -> T:
        """Return ``data`` as a non-optional value.

        Raises:
            MissingDataError: If ``data`` is ``None``. Use ``.data`` directly
                for a ``None``-safe alternative.
        """
        if self.data is None:
            raise MissingDataError(
                "Endpoint returned no data (data=None). Use .data (will be None) or don't access .value"
            )

        return self.data
