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

from __future__ import annotations
from datetime import datetime
from paygentic_sdk.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
    UnrecognizedStr,
)
from paygentic_sdk.utils import validate_const
import pydantic
from pydantic import model_serializer
from pydantic.functional_validators import AfterValidator
from typing import Dict, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypedDict


MeteredEntitlementDetailObject = Literal["entitlement",]


MeteredEntitlementDetailStatus = Union[
    Literal[
        "active",
        "canceled",
        "expired",
    ],
    UnrecognizedStr,
]
r"""Current status of the entitlement."""


class MeteredEntitlementDetailTypedDict(TypedDict):
    r"""Common fields shared by all entitlement types."""

    id: str
    r"""Unique identifier for the entitlement."""
    customer_id: str
    r"""Unique identifier for a customer"""
    feature_id: str
    r"""The feature this entitlement grants access to."""
    feature_key: str
    r"""The unique key identifying the feature."""
    status: MeteredEntitlementDetailStatus
    r"""Current status of the entitlement."""
    active_from: datetime
    r"""When the entitlement becomes active."""
    has_access: bool
    r"""Whether the customer currently has active access to this entitlement."""
    is_soft_limit: bool
    r"""When false (hard limit), access is blocked when balance is exhausted and overage is not charged on invoices. When true (soft limit), access continues past the grant and overage is charged at the per-unit rate."""
    balance: float
    r"""Remaining grant balance for the current period."""
    usage_in_period: float
    r"""Total usage consumed in the current billing period."""
    overage: float
    r"""Amount of usage exceeding the granted balance."""
    object: NotRequired[MeteredEntitlementDetailObject]
    feature_type: Literal["metered"]
    subscription_id: NotRequired[Nullable[str]]
    r"""The subscription this entitlement is associated with, if any."""
    active_to: NotRequired[Nullable[datetime]]
    r"""When the entitlement expires. Null means no expiration."""
    metadata: NotRequired[Dict[str, str]]
    r"""Additional metadata for the entitlement."""
    current_period_start: NotRequired[Nullable[datetime]]
    r"""Start of the current usage period."""
    current_period_end: NotRequired[Nullable[datetime]]
    r"""End of the current usage period."""


class MeteredEntitlementDetail(BaseModel):
    r"""Common fields shared by all entitlement types."""

    id: str
    r"""Unique identifier for the entitlement."""

    customer_id: Annotated[str, pydantic.Field(alias="customerId")]
    r"""Unique identifier for a customer"""

    feature_id: Annotated[str, pydantic.Field(alias="featureId")]
    r"""The feature this entitlement grants access to."""

    feature_key: Annotated[str, pydantic.Field(alias="featureKey")]
    r"""The unique key identifying the feature."""

    status: MeteredEntitlementDetailStatus
    r"""Current status of the entitlement."""

    active_from: Annotated[datetime, pydantic.Field(alias="activeFrom")]
    r"""When the entitlement becomes active."""

    has_access: Annotated[bool, pydantic.Field(alias="hasAccess")]
    r"""Whether the customer currently has active access to this entitlement."""

    is_soft_limit: Annotated[bool, pydantic.Field(alias="isSoftLimit")]
    r"""When false (hard limit), access is blocked when balance is exhausted and overage is not charged on invoices. When true (soft limit), access continues past the grant and overage is charged at the per-unit rate."""

    balance: float
    r"""Remaining grant balance for the current period."""

    usage_in_period: Annotated[float, pydantic.Field(alias="usageInPeriod")]
    r"""Total usage consumed in the current billing period."""

    overage: float
    r"""Amount of usage exceeding the granted balance."""

    object: Optional[MeteredEntitlementDetailObject] = "entitlement"

    feature_type: Annotated[
        Annotated[Literal["metered"], AfterValidator(validate_const("metered"))],
        pydantic.Field(alias="featureType"),
    ] = "metered"

    subscription_id: Annotated[
        OptionalNullable[str], pydantic.Field(alias="subscriptionId")
    ] = UNSET
    r"""The subscription this entitlement is associated with, if any."""

    active_to: Annotated[
        OptionalNullable[datetime], pydantic.Field(alias="activeTo")
    ] = UNSET
    r"""When the entitlement expires. Null means no expiration."""

    metadata: Optional[Dict[str, str]] = None
    r"""Additional metadata for the entitlement."""

    current_period_start: Annotated[
        OptionalNullable[datetime], pydantic.Field(alias="currentPeriodStart")
    ] = UNSET
    r"""Start of the current usage period."""

    current_period_end: Annotated[
        OptionalNullable[datetime], pydantic.Field(alias="currentPeriodEnd")
    ] = UNSET
    r"""End of the current usage period."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "object",
                "subscriptionId",
                "activeTo",
                "metadata",
                "currentPeriodStart",
                "currentPeriodEnd",
            ]
        )
        nullable_fields = set(
            ["subscriptionId", "activeTo", "currentPeriodStart", "currentPeriodEnd"]
        )
        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))
            is_nullable_and_explicitly_set = (
                k in nullable_fields
                and (self.__pydantic_fields_set__.intersection({n}))  # pylint: disable=no-member
            )

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

        return m


try:
    MeteredEntitlementDetail.model_rebuild()
except NameError:
    pass
