"""Modelos comuns reaproveitados em múltiplos recursos."""

from __future__ import annotations

from typing import Any, Generic, TypeVar

from pydantic import Field

from .base import AbacaModel, BaseResponse

T = TypeVar("T")


class Money(AbacaModel):
    """Representa um valor monetário em centavos.

    A API da AbacatePay trabalha exclusivamente com valores inteiros em
    centavos. Este wrapper documenta isso explicitamente e oferece helpers
    de conversão para usuários que preferem trabalhar com `float` em reais.
    """

    amount: int = Field(..., ge=0, description="Valor em centavos. Ex.: 10000 = R$ 100,00.")
    currency: str = Field(default="BRL", description="ISO 4217. AbacatePay sempre BRL.")

    @classmethod
    def from_brl(cls, brl: float) -> Money:
        """Constrói a partir de reais (multiplicando por 100 e arredondando)."""
        return cls(amount=round(brl * 100), currency="BRL")

    @property
    def to_brl(self) -> float:
        """Retorna o valor em reais (float)."""
        return self.amount / 100


class Address(AbacaModel):
    """Endereço opcional usado em alguns recursos (ex.: customers, payouts)."""

    zip_code: str | None = Field(default=None, alias="zipCode")
    street: str | None = None
    number: str | None = None
    complement: str | None = None
    neighborhood: str | None = None
    city: str | None = None
    state: str | None = None
    country: str | None = Field(default=None, description="ISO 3166-1 alpha-2.")


class APIEnvelope(BaseResponse, Generic[T]):
    """Representação opcional do envelope `{data, error, success}` da API.

    Em uso normal, o transporte já desempacota `data` e levanta exceção quando
    `error` está presente — esta classe existe apenas para casos em que o
    desenvolvedor quer inspecionar a resposta crua.
    """

    data: T | None = None
    error: Any | None = None
    success: bool | None = None


__all__ = ["APIEnvelope", "Address", "Money"]
