"""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 true, access is granted even when balance is exhausted."""
    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 true, access is granted even when balance is exhausted."""

    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
