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

from __future__ import annotations
from .address import Address, AddressTypedDict
from .attachedcustomfield import AttachedCustomField, AttachedCustomFieldTypedDict
from .checkoutbillingaddressfields import (
    CheckoutBillingAddressFields,
    CheckoutBillingAddressFieldsTypedDict,
)
from .checkoutdiscountfixedonceforeverduration import (
    CheckoutDiscountFixedOnceForeverDuration,
    CheckoutDiscountFixedOnceForeverDurationTypedDict,
)
from .checkoutdiscountfixedrepeatduration import (
    CheckoutDiscountFixedRepeatDuration,
    CheckoutDiscountFixedRepeatDurationTypedDict,
)
from .checkoutdiscountpercentageonceforeverduration import (
    CheckoutDiscountPercentageOnceForeverDuration,
    CheckoutDiscountPercentageOnceForeverDurationTypedDict,
)
from .checkoutdiscountpercentagerepeatduration import (
    CheckoutDiscountPercentageRepeatDuration,
    CheckoutDiscountPercentageRepeatDurationTypedDict,
)
from .checkoutorganization import CheckoutOrganization, CheckoutOrganizationTypedDict
from .checkoutproduct import CheckoutProduct, CheckoutProductTypedDict
from .checkoutstatus import CheckoutStatus
from .legacyrecurringproductprice import (
    LegacyRecurringProductPrice,
    LegacyRecurringProductPriceTypedDict,
)
from .paymentprocessor import PaymentProcessor
from .productprice import ProductPrice, ProductPriceTypedDict
from .trialinterval import TrialInterval
from datetime import datetime
from polar_sdk.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
import pydantic
from pydantic import model_serializer
from typing import Dict, List, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


CheckoutPublicCustomFieldDataTypedDict = TypeAliasType(
    "CheckoutPublicCustomFieldDataTypedDict", Union[str, int, bool, datetime]
)


CheckoutPublicCustomFieldData = TypeAliasType(
    "CheckoutPublicCustomFieldData", Union[str, int, bool, datetime]
)


CheckoutPublicProductPriceTypedDict = TypeAliasType(
    "CheckoutPublicProductPriceTypedDict",
    Union[LegacyRecurringProductPriceTypedDict, ProductPriceTypedDict],
)


CheckoutPublicProductPrice = TypeAliasType(
    "CheckoutPublicProductPrice", Union[LegacyRecurringProductPrice, ProductPrice]
)


CheckoutPublicPricesTypedDict = TypeAliasType(
    "CheckoutPublicPricesTypedDict",
    Union[LegacyRecurringProductPriceTypedDict, ProductPriceTypedDict],
)


CheckoutPublicPrices = TypeAliasType(
    "CheckoutPublicPrices", Union[LegacyRecurringProductPrice, ProductPrice]
)


CheckoutPublicDiscountTypedDict = TypeAliasType(
    "CheckoutPublicDiscountTypedDict",
    Union[
        CheckoutDiscountPercentageOnceForeverDurationTypedDict,
        CheckoutDiscountFixedOnceForeverDurationTypedDict,
        CheckoutDiscountPercentageRepeatDurationTypedDict,
        CheckoutDiscountFixedRepeatDurationTypedDict,
    ],
)


CheckoutPublicDiscount = TypeAliasType(
    "CheckoutPublicDiscount",
    Union[
        CheckoutDiscountPercentageOnceForeverDuration,
        CheckoutDiscountFixedOnceForeverDuration,
        CheckoutDiscountPercentageRepeatDuration,
        CheckoutDiscountFixedRepeatDuration,
    ],
)


class CheckoutPublicTypedDict(TypedDict):
    r"""Checkout session data retrieved using the client secret."""

    id: str
    r"""The ID of the object."""
    created_at: datetime
    r"""Creation timestamp of the object."""
    modified_at: Nullable[datetime]
    r"""Last modification timestamp of the object."""
    payment_processor: PaymentProcessor
    status: CheckoutStatus
    client_secret: str
    r"""Client secret used to update and complete the checkout session from the client."""
    url: str
    r"""URL where the customer can access the checkout session."""
    expires_at: datetime
    r"""Expiration date and time of the checkout session."""
    success_url: str
    r"""URL where the customer will be redirected after a successful payment."""
    return_url: Nullable[str]
    r"""When set, a back button will be shown in the checkout to return to this URL."""
    embed_origin: Nullable[str]
    r"""When checkout is embedded, represents the Origin of the page embedding the checkout. Used as a security measure to send messages only to the embedding page."""
    amount: int
    r"""Amount in cents, before discounts and taxes."""
    discount_amount: int
    r"""Discount amount in cents."""
    net_amount: int
    r"""Amount in cents, after discounts but before taxes."""
    tax_amount: Nullable[int]
    r"""Sales tax amount in cents. If `null`, it means there is no enough information yet to calculate it."""
    total_amount: int
    r"""Amount in cents, after discounts and taxes."""
    currency: str
    r"""Currency code of the checkout session."""
    allow_trial: Nullable[bool]
    r"""Whether to enable the trial period for the checkout session. If `false`, the trial period will be disabled, even if the selected product has a trial configured."""
    active_trial_interval: Nullable[TrialInterval]
    r"""Interval unit of the trial period, if any. This value is either set from the checkout, if `trial_interval` is set, or from the selected product."""
    active_trial_interval_count: Nullable[int]
    r"""Number of interval units of the trial period, if any. This value is either set from the checkout, if `trial_interval_count` is set, or from the selected product."""
    trial_end: Nullable[datetime]
    r"""End date and time of the trial period, if any."""
    organization_id: str
    r"""ID of the organization owning the checkout session."""
    product_id: Nullable[str]
    r"""ID of the product to checkout."""
    product_price_id: Nullable[str]
    r"""ID of the product price to checkout."""
    discount_id: Nullable[str]
    r"""ID of the discount applied to the checkout."""
    allow_discount_codes: bool
    r"""Whether to allow the customer to apply discount codes. If you apply a discount through `discount_id`, it'll still be applied, but the customer won't be able to change it."""
    require_billing_address: bool
    r"""Whether to require the customer to fill their full billing address, instead of just the country. Customers in the US will always be required to fill their full address, regardless of this setting. If you preset the billing address, this setting will be automatically set to `true`."""
    is_discount_applicable: bool
    r"""Whether the discount is applicable to the checkout. Typically, free and custom prices are not discountable."""
    is_free_product_price: bool
    r"""Whether the product price is free, regardless of discounts."""
    is_payment_required: bool
    r"""Whether the checkout requires payment, e.g. in case of free products or discounts that cover the total amount."""
    is_payment_setup_required: bool
    r"""Whether the checkout requires setting up a payment method, regardless of the amount, e.g. subscriptions that have first free cycles."""
    is_payment_form_required: bool
    r"""Whether the checkout requires a payment form, whether because of a payment or payment method setup."""
    customer_id: Nullable[str]
    is_business_customer: bool
    r"""Whether the customer is a business or an individual. If `true`, the customer will be required to fill their full billing address and billing name."""
    customer_name: Nullable[str]
    r"""Name of the customer."""
    customer_email: Nullable[str]
    r"""Email address of the customer."""
    customer_ip_address: Nullable[str]
    customer_billing_name: Nullable[str]
    customer_billing_address: Nullable[AddressTypedDict]
    customer_tax_id: Nullable[str]
    payment_processor_metadata: Dict[str, str]
    billing_address_fields: CheckoutBillingAddressFieldsTypedDict
    products: List[CheckoutProductTypedDict]
    r"""List of products available to select."""
    product: Nullable[CheckoutProductTypedDict]
    r"""Product selected to checkout."""
    product_price: Nullable[CheckoutPublicProductPriceTypedDict]
    r"""Price of the selected product."""
    prices: Nullable[Dict[str, List[CheckoutPublicPricesTypedDict]]]
    r"""Mapping of product IDs to their list of prices."""
    discount: Nullable[CheckoutPublicDiscountTypedDict]
    organization: CheckoutOrganizationTypedDict
    attached_custom_fields: Nullable[List[AttachedCustomFieldTypedDict]]
    custom_field_data: NotRequired[
        Dict[str, Nullable[CheckoutPublicCustomFieldDataTypedDict]]
    ]
    r"""Key-value object storing custom field values."""
    seats: NotRequired[Nullable[int]]
    r"""Number of seats for seat-based pricing."""
    price_per_seat: NotRequired[Nullable[int]]
    r"""Price per seat in cents for the current seat count, based on the applicable tier. Only relevant for seat-based pricing."""


class CheckoutPublic(BaseModel):
    r"""Checkout session data retrieved using the client secret."""

    id: str
    r"""The ID of the object."""

    created_at: datetime
    r"""Creation timestamp of the object."""

    modified_at: Nullable[datetime]
    r"""Last modification timestamp of the object."""

    payment_processor: PaymentProcessor

    status: CheckoutStatus

    client_secret: str
    r"""Client secret used to update and complete the checkout session from the client."""

    url: str
    r"""URL where the customer can access the checkout session."""

    expires_at: datetime
    r"""Expiration date and time of the checkout session."""

    success_url: str
    r"""URL where the customer will be redirected after a successful payment."""

    return_url: Nullable[str]
    r"""When set, a back button will be shown in the checkout to return to this URL."""

    embed_origin: Nullable[str]
    r"""When checkout is embedded, represents the Origin of the page embedding the checkout. Used as a security measure to send messages only to the embedding page."""

    amount: int
    r"""Amount in cents, before discounts and taxes."""

    discount_amount: int
    r"""Discount amount in cents."""

    net_amount: int
    r"""Amount in cents, after discounts but before taxes."""

    tax_amount: Nullable[int]
    r"""Sales tax amount in cents. If `null`, it means there is no enough information yet to calculate it."""

    total_amount: int
    r"""Amount in cents, after discounts and taxes."""

    currency: str
    r"""Currency code of the checkout session."""

    allow_trial: Nullable[bool]
    r"""Whether to enable the trial period for the checkout session. If `false`, the trial period will be disabled, even if the selected product has a trial configured."""

    active_trial_interval: Nullable[TrialInterval]
    r"""Interval unit of the trial period, if any. This value is either set from the checkout, if `trial_interval` is set, or from the selected product."""

    active_trial_interval_count: Nullable[int]
    r"""Number of interval units of the trial period, if any. This value is either set from the checkout, if `trial_interval_count` is set, or from the selected product."""

    trial_end: Nullable[datetime]
    r"""End date and time of the trial period, if any."""

    organization_id: str
    r"""ID of the organization owning the checkout session."""

    product_id: Nullable[str]
    r"""ID of the product to checkout."""

    product_price_id: Annotated[
        Nullable[str],
        pydantic.Field(
            deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible."
        ),
    ]
    r"""ID of the product price to checkout."""

    discount_id: Nullable[str]
    r"""ID of the discount applied to the checkout."""

    allow_discount_codes: bool
    r"""Whether to allow the customer to apply discount codes. If you apply a discount through `discount_id`, it'll still be applied, but the customer won't be able to change it."""

    require_billing_address: bool
    r"""Whether to require the customer to fill their full billing address, instead of just the country. Customers in the US will always be required to fill their full address, regardless of this setting. If you preset the billing address, this setting will be automatically set to `true`."""

    is_discount_applicable: bool
    r"""Whether the discount is applicable to the checkout. Typically, free and custom prices are not discountable."""

    is_free_product_price: bool
    r"""Whether the product price is free, regardless of discounts."""

    is_payment_required: bool
    r"""Whether the checkout requires payment, e.g. in case of free products or discounts that cover the total amount."""

    is_payment_setup_required: bool
    r"""Whether the checkout requires setting up a payment method, regardless of the amount, e.g. subscriptions that have first free cycles."""

    is_payment_form_required: bool
    r"""Whether the checkout requires a payment form, whether because of a payment or payment method setup."""

    customer_id: Nullable[str]

    is_business_customer: bool
    r"""Whether the customer is a business or an individual. If `true`, the customer will be required to fill their full billing address and billing name."""

    customer_name: Nullable[str]
    r"""Name of the customer."""

    customer_email: Nullable[str]
    r"""Email address of the customer."""

    customer_ip_address: Nullable[str]

    customer_billing_name: Nullable[str]

    customer_billing_address: Nullable[Address]

    customer_tax_id: Nullable[str]

    payment_processor_metadata: Dict[str, str]

    billing_address_fields: CheckoutBillingAddressFields

    products: List[CheckoutProduct]
    r"""List of products available to select."""

    product: Nullable[CheckoutProduct]
    r"""Product selected to checkout."""

    product_price: Annotated[
        Nullable[CheckoutPublicProductPrice],
        pydantic.Field(
            deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible."
        ),
    ]
    r"""Price of the selected product."""

    prices: Nullable[Dict[str, List[CheckoutPublicPrices]]]
    r"""Mapping of product IDs to their list of prices."""

    discount: Nullable[CheckoutPublicDiscount]

    organization: CheckoutOrganization

    attached_custom_fields: Nullable[List[AttachedCustomField]]

    custom_field_data: Optional[Dict[str, Nullable[CheckoutPublicCustomFieldData]]] = (
        None
    )
    r"""Key-value object storing custom field values."""

    seats: OptionalNullable[int] = UNSET
    r"""Number of seats for seat-based pricing."""

    price_per_seat: OptionalNullable[int] = UNSET
    r"""Price per seat in cents for the current seat count, based on the applicable tier. Only relevant for seat-based pricing."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = ["custom_field_data", "seats", "price_per_seat"]
        nullable_fields = [
            "modified_at",
            "return_url",
            "embed_origin",
            "seats",
            "price_per_seat",
            "tax_amount",
            "allow_trial",
            "active_trial_interval",
            "active_trial_interval_count",
            "trial_end",
            "product_id",
            "product_price_id",
            "discount_id",
            "customer_id",
            "customer_name",
            "customer_email",
            "customer_ip_address",
            "customer_billing_name",
            "customer_billing_address",
            "customer_tax_id",
            "product",
            "product_price",
            "prices",
            "discount",
            "attached_custom_fields",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

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

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m
