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

from __future__ import annotations
from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from enum import Enum
import pydantic
from pydantic import model_serializer
from typing import Any, Dict, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class PaymentProcessor(str, Enum):
    r"""The payment processor via which the sale was made."""

    STRIPE = "stripe"
    SHOPIFY = "shopify"
    POLAR = "polar"
    PADDLE = "paddle"
    REVENUECAT = "revenuecat"
    CUSTOM = "custom"


class TrackSaleRequestBodyTypedDict(TypedDict):
    customer_external_id: str
    r"""The unique ID of the customer in your system. Will be used to identify and attribute all future events to this customer."""
    amount: int
    r"""The amount of the sale in cents (for all two-decimal currencies). If the sale is in a zero-decimal currency, pass the full integer value (e.g. `1437` JPY). Learn more: https://d.to/currency"""
    currency: NotRequired[str]
    r"""The currency of the sale. Accepts ISO 4217 currency codes. Sales will be automatically converted and stored as USD at the latest exchange rates. Learn more: https://d.to/currency"""
    event_name: NotRequired[str]
    r"""The name of the sale event. Recommended format: `Invoice paid` or `Subscription created`."""
    payment_processor: NotRequired[PaymentProcessor]
    r"""The payment processor via which the sale was made."""
    invoice_id: NotRequired[Nullable[str]]
    r"""The invoice ID of the sale. Can be used as a idempotency key – only one sale event can be recorded for a given invoice ID."""
    metadata: NotRequired[Nullable[Dict[str, Any]]]
    r"""Additional metadata to be stored with the sale event. Max 10,000 characters when stringified."""
    lead_event_name: NotRequired[Nullable[str]]
    r"""The name of the lead event that occurred before the sale (case-sensitive). This is used to associate the sale event with a particular lead event (instead of the latest lead event for a link-customer combination, which is the default behavior). For direct sale tracking, this field can also be used to specify the lead event name."""
    click_id: NotRequired[Nullable[str]]
    r"""[For direct sale tracking]: The unique ID of the click that the sale conversion event is attributed to. You can read this value from `dub_id` cookie."""
    customer_name: NotRequired[Nullable[str]]
    r"""[For direct sale tracking]: The name of the customer. If not passed, a random name will be generated (e.g. “Big Red Caribou”)."""
    customer_email: NotRequired[Nullable[str]]
    r"""[For direct sale tracking]: The email address of the customer."""
    customer_avatar: NotRequired[Nullable[str]]
    r"""[For direct sale tracking]: The avatar URL of the customer."""


class TrackSaleRequestBody(BaseModel):
    customer_external_id: Annotated[str, pydantic.Field(alias="customerExternalId")]
    r"""The unique ID of the customer in your system. Will be used to identify and attribute all future events to this customer."""

    amount: int
    r"""The amount of the sale in cents (for all two-decimal currencies). If the sale is in a zero-decimal currency, pass the full integer value (e.g. `1437` JPY). Learn more: https://d.to/currency"""

    currency: Optional[str] = "usd"
    r"""The currency of the sale. Accepts ISO 4217 currency codes. Sales will be automatically converted and stored as USD at the latest exchange rates. Learn more: https://d.to/currency"""

    event_name: Annotated[Optional[str], pydantic.Field(alias="eventName")] = "Purchase"
    r"""The name of the sale event. Recommended format: `Invoice paid` or `Subscription created`."""

    payment_processor: Annotated[
        Optional[PaymentProcessor], pydantic.Field(alias="paymentProcessor")
    ] = PaymentProcessor.CUSTOM
    r"""The payment processor via which the sale was made."""

    invoice_id: Annotated[OptionalNullable[str], pydantic.Field(alias="invoiceId")] = (
        None
    )
    r"""The invoice ID of the sale. Can be used as a idempotency key – only one sale event can be recorded for a given invoice ID."""

    metadata: OptionalNullable[Dict[str, Any]] = UNSET
    r"""Additional metadata to be stored with the sale event. Max 10,000 characters when stringified."""

    lead_event_name: Annotated[
        OptionalNullable[str], pydantic.Field(alias="leadEventName")
    ] = None
    r"""The name of the lead event that occurred before the sale (case-sensitive). This is used to associate the sale event with a particular lead event (instead of the latest lead event for a link-customer combination, which is the default behavior). For direct sale tracking, this field can also be used to specify the lead event name."""

    click_id: Annotated[OptionalNullable[str], pydantic.Field(alias="clickId")] = UNSET
    r"""[For direct sale tracking]: The unique ID of the click that the sale conversion event is attributed to. You can read this value from `dub_id` cookie."""

    customer_name: Annotated[
        OptionalNullable[str], pydantic.Field(alias="customerName")
    ] = None
    r"""[For direct sale tracking]: The name of the customer. If not passed, a random name will be generated (e.g. “Big Red Caribou”)."""

    customer_email: Annotated[
        OptionalNullable[str], pydantic.Field(alias="customerEmail")
    ] = None
    r"""[For direct sale tracking]: The email address of the customer."""

    customer_avatar: Annotated[
        OptionalNullable[str], pydantic.Field(alias="customerAvatar")
    ] = None
    r"""[For direct sale tracking]: The avatar URL of the customer."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "currency",
                "eventName",
                "paymentProcessor",
                "invoiceId",
                "metadata",
                "leadEventName",
                "clickId",
                "customerName",
                "customerEmail",
                "customerAvatar",
            ]
        )
        nullable_fields = set(
            [
                "invoiceId",
                "metadata",
                "leadEventName",
                "clickId",
                "customerName",
                "customerEmail",
                "customerAvatar",
            ]
        )
        null_default_fields = set(
            [
                "invoiceId",
                "leadEventName",
                "customerName",
                "customerEmail",
                "customerAvatar",
            ]
        )
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k)
            is_nullable_and_explicitly_set = (
                k in nullable_fields
                and (
                    self.__pydantic_fields_set__.intersection({n})
                    or k in null_default_fields
                )  # 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


class TrackSaleCustomerTypedDict(TypedDict):
    id: str
    name: Nullable[str]
    email: Nullable[str]
    avatar: Nullable[str]
    external_id: Nullable[str]


class TrackSaleCustomer(BaseModel):
    id: str

    name: Nullable[str]

    email: Nullable[str]

    avatar: Nullable[str]

    external_id: Annotated[Nullable[str], pydantic.Field(alias="externalId")]

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        serialized = handler(self)
        m = {}

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

            if val != UNSET_SENTINEL:
                m[k] = val

        return m


class SaleTypedDict(TypedDict):
    amount: float
    currency: str
    payment_processor: str
    invoice_id: Nullable[str]
    metadata: Nullable[Dict[str, Any]]


class Sale(BaseModel):
    amount: float

    currency: str

    payment_processor: Annotated[str, pydantic.Field(alias="paymentProcessor")]

    invoice_id: Annotated[Nullable[str], pydantic.Field(alias="invoiceId")]

    metadata: Nullable[Dict[str, Any]]

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        serialized = handler(self)
        m = {}

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

            if val != UNSET_SENTINEL:
                m[k] = val

        return m


class TrackSaleResponseBodyTypedDict(TypedDict):
    r"""A sale was tracked."""

    event_name: str
    customer: Nullable[TrackSaleCustomerTypedDict]
    sale: Nullable[SaleTypedDict]


class TrackSaleResponseBody(BaseModel):
    r"""A sale was tracked."""

    event_name: Annotated[str, pydantic.Field(alias="eventName")]

    customer: Nullable[TrackSaleCustomer]

    sale: Nullable[Sale]

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        serialized = handler(self)
        m = {}

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

            if val != UNSET_SENTINEL:
                m[k] = val

        return m
