"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""

from __future__ import annotations
from datetime import datetime
from paygentic_sdk.types import BaseModel, UNSET_SENTINEL
import pydantic
from pydantic import model_serializer
from typing import Dict, List, Literal, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


UsageEventObject = Literal["usageEvent",]


class BillingTypedDict(TypedDict):
    r"""Billing information for the usage event when it has been billed. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""

    billing_event_id: NotRequired[str]
    r"""Billing event identifier linked to this consumption record"""
    currency: NotRequired[str]
    r"""Three-letter ISO 4217 currency code. Sample values: 'USD' for US dollars, 'EUR' for euros, 'GBP' for British pounds"""
    invoice_id: NotRequired[str]
    r"""Invoice V2 period ID (subscription-anchor based billing). Null for legacy billing."""
    price: NotRequired[int]
    r"""Price amount in the smallest currency unit, excluding tax. Sample values: 1000000000 represents $1.00 in atomic units, 5000000000 represents $5.00 in atomic units"""
    total_amount: NotRequired[int]
    r"""Final amount including tax in the smallest currency unit. Sample values: 1085000000 equals $1.085 total (price + tax) in atomic units, 5500000000 equals $5.50 total in atomic units. Calculated as price plus totalTax."""
    total_tax: NotRequired[int]
    r"""Total tax amount in the smallest currency unit. Sample values: 85000000 represents $0.085 tax in atomic units, 100000000 represents $0.10 tax in atomic units"""


class Billing(BaseModel):
    r"""Billing information for the usage event when it has been billed. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""

    billing_event_id: Annotated[
        Optional[str], pydantic.Field(alias="billingEventId")
    ] = None
    r"""Billing event identifier linked to this consumption record"""

    currency: Optional[str] = None
    r"""Three-letter ISO 4217 currency code. Sample values: 'USD' for US dollars, 'EUR' for euros, 'GBP' for British pounds"""

    invoice_id: Annotated[Optional[str], pydantic.Field(alias="invoiceId")] = None
    r"""Invoice V2 period ID (subscription-anchor based billing). Null for legacy billing."""

    price: Optional[int] = None
    r"""Price amount in the smallest currency unit, excluding tax. Sample values: 1000000000 represents $1.00 in atomic units, 5000000000 represents $5.00 in atomic units"""

    total_amount: Annotated[Optional[int], pydantic.Field(alias="totalAmount")] = None
    r"""Final amount including tax in the smallest currency unit. Sample values: 1085000000 equals $1.085 total (price + tax) in atomic units, 5500000000 equals $5.50 total in atomic units. Calculated as price plus totalTax."""

    total_tax: Annotated[Optional[int], pydantic.Field(alias="totalTax")] = None
    r"""Total tax amount in the smallest currency unit. Sample values: 85000000 represents $0.085 tax in atomic units, 100000000 represents $0.10 tax in atomic units"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "billingEventId",
                "currency",
                "invoiceId",
                "price",
                "totalAmount",
                "totalTax",
            ]
        )
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class UsageEventPropertyTypedDict(TypedDict):
    billable_metric_id: str
    quantity: int
    r"""Consumption quantity must be a positive whole number. Sample values: 1 for single unit, 100 for one hundred units, 2500 for tokens consumed"""
    price: NotRequired[str]
    r"""Custom price override in decimal dollars. Sample values: '0.000012' sets $0.000012 per unit, '0.50' sets $0.50 per unit, '1.25' sets $1.25 per unit"""


class UsageEventProperty(BaseModel):
    billable_metric_id: Annotated[str, pydantic.Field(alias="billableMetricId")]

    quantity: int
    r"""Consumption quantity must be a positive whole number. Sample values: 1 for single unit, 100 for one hundred units, 2500 for tokens consumed"""

    price: Optional[str] = None
    r"""Custom price override in decimal dollars. Sample values: '0.000012' sets $0.000012 per unit, '0.50' sets $0.50 per unit, '1.25' sets $1.25 per unit"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["price"])
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class RefundTypedDict(TypedDict):
    r"""Refund information for the usage event when it has been refunded. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""

    reason: NotRequired[str]
    r"""Reason for the refund. Sample values: 'Customer request', 'Billing error', 'Service credit', 'System error correction'"""
    refunded_at: NotRequired[datetime]
    r"""Timestamp when the usage event was refunded"""


class Refund(BaseModel):
    r"""Refund information for the usage event when it has been refunded. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""

    reason: Optional[str] = None
    r"""Reason for the refund. Sample values: 'Customer request', 'Billing error', 'Service credit', 'System error correction'"""

    refunded_at: Annotated[Optional[datetime], pydantic.Field(alias="refundedAt")] = (
        None
    )
    r"""Timestamp when the usage event was refunded"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["reason", "refundedAt"])
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class UsageEventTypedDict(TypedDict):
    id: str
    r"""Unique identifier for a usage event"""
    object: UsageEventObject
    created_at: datetime
    customer_id: str
    merchant_id: str
    properties: List[UsageEventPropertyTypedDict]
    subscription_id: str
    timestamp: datetime
    billing: NotRequired[BillingTypedDict]
    r"""Billing information for the usage event when it has been billed. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""
    consumer_id: NotRequired[str]
    description: NotRequired[str]
    r"""Readable summary explaining what triggered this consumption event. Sample values: 'Claude language model text generation', 'Customer data warehouse storage allocation', 'DALL-E image creation batch job', 'GPT-4 fine-tuning compute session', 'Vector database query operations'"""
    entitlement_id: NotRequired[str]
    r"""Commitment identifier used for this consumption event. Sample values: 'com_abc123xyz', 'com_789def456'"""
    idempotency_key: NotRequired[str]
    metadata: NotRequired[Dict[str, str]]
    refund: NotRequired[RefundTypedDict]
    r"""Refund information for the usage event when it has been refunded. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""


class UsageEvent(BaseModel):
    id: str
    r"""Unique identifier for a usage event"""

    object: UsageEventObject

    created_at: Annotated[datetime, pydantic.Field(alias="createdAt")]

    customer_id: Annotated[str, pydantic.Field(alias="customerId")]

    merchant_id: Annotated[str, pydantic.Field(alias="merchantId")]

    properties: List[UsageEventProperty]

    subscription_id: Annotated[str, pydantic.Field(alias="subscriptionId")]

    timestamp: datetime

    billing: Optional[Billing] = None
    r"""Billing information for the usage event when it has been billed. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""

    consumer_id: Annotated[Optional[str], pydantic.Field(alias="consumerId")] = None

    description: Optional[str] = None
    r"""Readable summary explaining what triggered this consumption event. Sample values: 'Claude language model text generation', 'Customer data warehouse storage allocation', 'DALL-E image creation batch job', 'GPT-4 fine-tuning compute session', 'Vector database query operations'"""

    entitlement_id: Annotated[Optional[str], pydantic.Field(alias="entitlementId")] = (
        None
    )
    r"""Commitment identifier used for this consumption event. Sample values: 'com_abc123xyz', 'com_789def456'"""

    idempotency_key: Annotated[
        Optional[str], pydantic.Field(alias="idempotencyKey")
    ] = None

    metadata: Optional[Dict[str, str]] = None

    refund: Optional[Refund] = None
    r"""Refund information for the usage event when it has been refunded. This object is populated by the server and returned in GET and PATCH responses. It cannot be set directly in request bodies."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "billing",
                "consumerId",
                "description",
                "entitlementId",
                "idempotencyKey",
                "metadata",
                "refund",
            ]
        )
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


try:
    Billing.model_rebuild()
except NameError:
    pass
try:
    UsageEventProperty.model_rebuild()
except NameError:
    pass
try:
    Refund.model_rebuild()
except NameError:
    pass
try:
    UsageEvent.model_rebuild()
except NameError:
    pass
