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

from __future__ import annotations
from .addressinput import AddressInput, AddressInputTypedDict
from datetime import datetime
from polar_sdk.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from pydantic import model_serializer
from typing import Dict, List, Optional, Union
from typing_extensions import NotRequired, TypeAliasType, TypedDict


CheckoutCreateMetadataTypedDict = TypeAliasType(
    "CheckoutCreateMetadataTypedDict", Union[str, int, float, bool]
)


CheckoutCreateMetadata = TypeAliasType(
    "CheckoutCreateMetadata", Union[str, int, float, bool]
)


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


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


CheckoutCreateCustomerMetadataTypedDict = TypeAliasType(
    "CheckoutCreateCustomerMetadataTypedDict", Union[str, int, float, bool]
)


CheckoutCreateCustomerMetadata = TypeAliasType(
    "CheckoutCreateCustomerMetadata", Union[str, int, float, bool]
)


class CheckoutCreateTypedDict(TypedDict):
    r"""Create a new checkout session from a list of products.
    Customers will be able to switch between those products.

    Metadata set on the checkout will be copied
    to the resulting order and/or subscription.
    """

    products: List[str]
    r"""List of product IDs available to select at that checkout. The first one will be selected by default."""
    metadata: NotRequired[Dict[str, CheckoutCreateMetadataTypedDict]]
    r"""Key-value object allowing you to store additional information.

    The key must be a string with a maximum length of **40 characters**.
    The value must be either:

    * A string with a maximum length of **500 characters**
    * An integer
    * A floating-point number
    * A boolean

    You can store up to **50 key-value pairs**.
    """
    custom_field_data: NotRequired[
        Dict[str, Nullable[CheckoutCreateCustomFieldDataTypedDict]]
    ]
    r"""Key-value object storing custom field values."""
    discount_id: NotRequired[Nullable[str]]
    r"""ID of the discount to apply to the checkout."""
    allow_discount_codes: NotRequired[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: NotRequired[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`."""
    amount: NotRequired[Nullable[int]]
    customer_id: NotRequired[Nullable[str]]
    r"""ID of an existing customer in the organization. The customer data will be pre-filled in the checkout form. The resulting order will be linked to this customer."""
    is_business_customer: NotRequired[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."""
    external_customer_id: NotRequired[Nullable[str]]
    r"""ID of the customer in your system. If a matching customer exists on Polar, the resulting order will be linked to this customer. Otherwise, a new customer will be created with this external ID set."""
    customer_name: NotRequired[Nullable[str]]
    customer_email: NotRequired[Nullable[str]]
    customer_ip_address: NotRequired[Nullable[str]]
    customer_billing_name: NotRequired[Nullable[str]]
    customer_billing_address: NotRequired[Nullable[AddressInputTypedDict]]
    customer_tax_id: NotRequired[Nullable[str]]
    customer_metadata: NotRequired[Dict[str, CheckoutCreateCustomerMetadataTypedDict]]
    r"""Key-value object allowing you to store additional information that'll be copied to the created customer.

    The key must be a string with a maximum length of **40 characters**.
    The value must be either:

    * A string with a maximum length of **500 characters**
    * An integer
    * A floating-point number
    * A boolean

    You can store up to **50 key-value pairs**.
    """
    subscription_id: NotRequired[Nullable[str]]
    r"""ID of a subscription to upgrade. It must be on a free pricing. If checkout is successful, metadata set on this checkout will be copied to the subscription, and existing keys will be overwritten."""
    success_url: NotRequired[Nullable[str]]
    r"""URL where the customer will be redirected after a successful payment.You can add the `checkout_id={CHECKOUT_ID}` query parameter to retrieve the checkout session id."""
    embed_origin: NotRequired[Nullable[str]]
    r"""If you plan to embed the checkout session, set this to the Origin of the embedding page. It'll allow the Polar iframe to communicate with the parent page."""


class CheckoutCreate(BaseModel):
    r"""Create a new checkout session from a list of products.
    Customers will be able to switch between those products.

    Metadata set on the checkout will be copied
    to the resulting order and/or subscription.
    """

    products: List[str]
    r"""List of product IDs available to select at that checkout. The first one will be selected by default."""

    metadata: Optional[Dict[str, CheckoutCreateMetadata]] = None
    r"""Key-value object allowing you to store additional information.

    The key must be a string with a maximum length of **40 characters**.
    The value must be either:

    * A string with a maximum length of **500 characters**
    * An integer
    * A floating-point number
    * A boolean

    You can store up to **50 key-value pairs**.
    """

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

    discount_id: OptionalNullable[str] = UNSET
    r"""ID of the discount to apply to the checkout."""

    allow_discount_codes: Optional[bool] = True
    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: Optional[bool] = False
    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`."""

    amount: OptionalNullable[int] = UNSET

    customer_id: OptionalNullable[str] = UNSET
    r"""ID of an existing customer in the organization. The customer data will be pre-filled in the checkout form. The resulting order will be linked to this customer."""

    is_business_customer: Optional[bool] = False
    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."""

    external_customer_id: OptionalNullable[str] = UNSET
    r"""ID of the customer in your system. If a matching customer exists on Polar, the resulting order will be linked to this customer. Otherwise, a new customer will be created with this external ID set."""

    customer_name: OptionalNullable[str] = UNSET

    customer_email: OptionalNullable[str] = UNSET

    customer_ip_address: OptionalNullable[str] = UNSET

    customer_billing_name: OptionalNullable[str] = UNSET

    customer_billing_address: OptionalNullable[AddressInput] = UNSET

    customer_tax_id: OptionalNullable[str] = UNSET

    customer_metadata: Optional[Dict[str, CheckoutCreateCustomerMetadata]] = None
    r"""Key-value object allowing you to store additional information that'll be copied to the created customer.

    The key must be a string with a maximum length of **40 characters**.
    The value must be either:

    * A string with a maximum length of **500 characters**
    * An integer
    * A floating-point number
    * A boolean

    You can store up to **50 key-value pairs**.
    """

    subscription_id: OptionalNullable[str] = UNSET
    r"""ID of a subscription to upgrade. It must be on a free pricing. If checkout is successful, metadata set on this checkout will be copied to the subscription, and existing keys will be overwritten."""

    success_url: OptionalNullable[str] = UNSET
    r"""URL where the customer will be redirected after a successful payment.You can add the `checkout_id={CHECKOUT_ID}` query parameter to retrieve the checkout session id."""

    embed_origin: OptionalNullable[str] = UNSET
    r"""If you plan to embed the checkout session, set this to the Origin of the embedding page. It'll allow the Polar iframe to communicate with the parent page."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "metadata",
            "custom_field_data",
            "discount_id",
            "allow_discount_codes",
            "require_billing_address",
            "amount",
            "customer_id",
            "is_business_customer",
            "external_customer_id",
            "customer_name",
            "customer_email",
            "customer_ip_address",
            "customer_billing_name",
            "customer_billing_address",
            "customer_tax_id",
            "customer_metadata",
            "subscription_id",
            "success_url",
            "embed_origin",
        ]
        nullable_fields = [
            "discount_id",
            "amount",
            "customer_id",
            "external_customer_id",
            "customer_name",
            "customer_email",
            "customer_ip_address",
            "customer_billing_name",
            "customer_billing_address",
            "customer_tax_id",
            "subscription_id",
            "success_url",
            "embed_origin",
        ]
        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
