"""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
from paygentic_sdk.utils import validate_const
import pydantic
from pydantic import Field, model_serializer
from pydantic.functional_validators import AfterValidator
from typing import Any, Dict, Literal, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


class UsagePeriodTypedDict(TypedDict):
    interval: str
    r"""ISO 8601 duration for the usage period, e.g. P1D, P1W, P1M, P1Y."""
    anchor: NotRequired[datetime]
    r"""Optional anchor date-time for period alignment."""


class UsagePeriod(BaseModel):
    interval: str
    r"""ISO 8601 duration for the usage period, e.g. P1D, P1W, P1M, P1Y."""

    anchor: Optional[datetime] = None
    r"""Optional anchor date-time for period alignment."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["anchor"])
        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 EntitlementTemplateMeteredTypedDict(TypedDict):
    usage_period: UsagePeriodTypedDict
    type: Literal["metered"]
    is_soft_limit: NotRequired[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."""
    issue_after_reset: NotRequired[float]
    r"""Amount of grants to issue after each period reset."""
    issue_after_reset_priority: NotRequired[int]
    r"""Priority for grants issued after reset."""
    preserve_overage_at_reset: NotRequired[bool]
    r"""When true, overage from the previous period carries over."""
    reset_max_rollover: NotRequired[float]
    r"""Maximum amount of unused balance that rolls over on reset."""
    reset_min_rollover: NotRequired[float]
    r"""Minimum amount of balance guaranteed to roll over on reset."""


class EntitlementTemplateMetered(BaseModel):
    usage_period: Annotated[UsagePeriod, pydantic.Field(alias="usagePeriod")]

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

    is_soft_limit: Annotated[Optional[bool], pydantic.Field(alias="isSoftLimit")] = None
    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."""

    issue_after_reset: Annotated[
        Optional[float], pydantic.Field(alias="issueAfterReset")
    ] = None
    r"""Amount of grants to issue after each period reset."""

    issue_after_reset_priority: Annotated[
        Optional[int], pydantic.Field(alias="issueAfterResetPriority")
    ] = None
    r"""Priority for grants issued after reset."""

    preserve_overage_at_reset: Annotated[
        Optional[bool], pydantic.Field(alias="preserveOverageAtReset")
    ] = None
    r"""When true, overage from the previous period carries over."""

    reset_max_rollover: Annotated[
        Optional[float], pydantic.Field(alias="resetMaxRollover")
    ] = None
    r"""Maximum amount of unused balance that rolls over on reset."""

    reset_min_rollover: Annotated[
        Optional[float], pydantic.Field(alias="resetMinRollover")
    ] = None
    r"""Minimum amount of balance guaranteed to roll over on reset."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "isSoftLimit",
                "issueAfterReset",
                "issueAfterResetPriority",
                "preserveOverageAtReset",
                "resetMaxRollover",
                "resetMinRollover",
            ]
        )
        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 EntitlementTemplateStaticTypedDict(TypedDict):
    config: Dict[str, Any]
    r"""Configuration values for the entitlement."""
    type: Literal["static"]


class EntitlementTemplateStatic(BaseModel):
    config: Dict[str, Any]
    r"""Configuration values for the entitlement."""

    type: Annotated[
        Annotated[Literal["static"], AfterValidator(validate_const("static"))],
        pydantic.Field(alias="type"),
    ] = "static"


class EntitlementTemplateBooleanTypedDict(TypedDict):
    type: Literal["boolean"]


class EntitlementTemplateBoolean(BaseModel):
    type: Annotated[
        Annotated[Literal["boolean"], AfterValidator(validate_const("boolean"))],
        pydantic.Field(alias="type"),
    ] = "boolean"


EntitlementTemplateTypedDict = TypeAliasType(
    "EntitlementTemplateTypedDict",
    Union[
        EntitlementTemplateBooleanTypedDict,
        EntitlementTemplateStaticTypedDict,
        EntitlementTemplateMeteredTypedDict,
    ],
)
r"""Template for the entitlement. Boolean for simple on/off features, static for features with configuration, metered for usage-based features."""


EntitlementTemplate = Annotated[
    Union[
        EntitlementTemplateBoolean,
        EntitlementTemplateStatic,
        EntitlementTemplateMetered,
    ],
    Field(discriminator="type"),
]
r"""Template for the entitlement. Boolean for simple on/off features, static for features with configuration, metered for usage-based features."""


try:
    EntitlementTemplateMetered.model_rebuild()
except NameError:
    pass
try:
    EntitlementTemplateStatic.model_rebuild()
except NameError:
    pass
try:
    EntitlementTemplateBoolean.model_rebuild()
except NameError:
    pass
