"""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 dub.utils import FieldMetadata, PathParamMetadata, RequestMetadata
from enum import Enum
import pydantic
from pydantic import model_serializer
from typing import Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class Status(str, Enum):
    r"""Useful for marking a commission as refunded, duplicate, canceled, or fraudulent. Takes precedence over `amount` and `modifyAmount`. When a commission is marked as refunded, duplicate, canceled, or fraudulent, it will be omitted from the payout, and the payout amount will be recalculated accordingly. Paid commissions cannot be updated."""

    REFUNDED = "refunded"
    DUPLICATE = "duplicate"
    CANCELED = "canceled"
    FRAUD = "fraud"


class UpdateCommissionRequestBodyTypedDict(TypedDict):
    amount: NotRequired[float]
    r"""The new absolute amount for the sale. Paid commissions cannot be updated."""
    modify_amount: NotRequired[float]
    r"""Modify the current sale amount: use positive values to increase the amount, negative values to decrease it. Takes precedence over `amount`. Paid commissions cannot be updated."""
    currency: NotRequired[str]
    r"""The currency of the sale amount to update. Accepts ISO 4217 currency codes."""
    status: NotRequired[Status]
    r"""Useful for marking a commission as refunded, duplicate, canceled, or fraudulent. Takes precedence over `amount` and `modifyAmount`. When a commission is marked as refunded, duplicate, canceled, or fraudulent, it will be omitted from the payout, and the payout amount will be recalculated accordingly. Paid commissions cannot be updated."""


class UpdateCommissionRequestBody(BaseModel):
    amount: Optional[float] = None
    r"""The new absolute amount for the sale. Paid commissions cannot be updated."""

    modify_amount: Annotated[Optional[float], pydantic.Field(alias="modifyAmount")] = (
        None
    )
    r"""Modify the current sale amount: use positive values to increase the amount, negative values to decrease it. Takes precedence over `amount`. Paid commissions cannot be updated."""

    currency: Optional[str] = "usd"
    r"""The currency of the sale amount to update. Accepts ISO 4217 currency codes."""

    status: Optional[Status] = None
    r"""Useful for marking a commission as refunded, duplicate, canceled, or fraudulent. Takes precedence over `amount` and `modifyAmount`. When a commission is marked as refunded, duplicate, canceled, or fraudulent, it will be omitted from the payout, and the payout amount will be recalculated accordingly. Paid commissions cannot be updated."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["amount", "modifyAmount", "currency", "status"])
        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:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class UpdateCommissionRequestTypedDict(TypedDict):
    id: str
    r"""The commission's unique ID on Dub."""
    request_body: NotRequired[UpdateCommissionRequestBodyTypedDict]


class UpdateCommissionRequest(BaseModel):
    id: Annotated[
        str, FieldMetadata(path=PathParamMetadata(style="simple", explode=False))
    ]
    r"""The commission's unique ID on Dub."""

    request_body: Annotated[
        Optional[UpdateCommissionRequestBody],
        FieldMetadata(request=RequestMetadata(media_type="application/json")),
    ] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["RequestBody"])
        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:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class UpdateCommissionType(str, Enum):
    CLICK = "click"
    LEAD = "lead"
    SALE = "sale"
    CUSTOM = "custom"


class UpdateCommissionStatus(str, Enum):
    PENDING = "pending"
    PROCESSED = "processed"
    PAID = "paid"
    REFUNDED = "refunded"
    DUPLICATE = "duplicate"
    FRAUD = "fraud"
    CANCELED = "canceled"


class UpdateCommissionPartnerTypedDict(TypedDict):
    id: str
    r"""The partner's unique ID on Dub."""
    name: str
    r"""The partner's full legal name."""
    email: Nullable[str]
    r"""The partner's email address. Should be a unique value across Dub."""
    image: Nullable[str]
    r"""The partner's avatar image."""
    payouts_enabled_at: Nullable[str]
    r"""The date when the partner enabled payouts."""
    country: Nullable[str]
    r"""The partner's country (required for tax purposes)."""
    group_id: NotRequired[Nullable[str]]
    r"""The partner's group ID on Dub."""


class UpdateCommissionPartner(BaseModel):
    id: str
    r"""The partner's unique ID on Dub."""

    name: str
    r"""The partner's full legal name."""

    email: Nullable[str]
    r"""The partner's email address. Should be a unique value across Dub."""

    image: Nullable[str]
    r"""The partner's avatar image."""

    payouts_enabled_at: Annotated[
        Nullable[str], pydantic.Field(alias="payoutsEnabledAt")
    ]
    r"""The date when the partner enabled payouts."""

    country: Nullable[str]
    r"""The partner's country (required for tax purposes)."""

    group_id: Annotated[OptionalNullable[str], pydantic.Field(alias="groupId")] = UNSET
    r"""The partner's group ID on Dub."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["groupId"])
        nullable_fields = set(
            ["email", "image", "payoutsEnabledAt", "country", "groupId"]
        )
        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}))  # 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 UpdateCommissionCustomerTypedDict(TypedDict):
    id: str
    r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
    name: str
    r"""Name of the customer."""
    external_id: str
    r"""Unique identifier for the customer in the client's app."""
    created_at: str
    r"""The date the customer was created (usually the signup date or trial start date)."""
    email: NotRequired[Nullable[str]]
    r"""Email of the customer."""
    avatar: NotRequired[Nullable[str]]
    r"""Avatar URL of the customer."""
    stripe_customer_id: NotRequired[Nullable[str]]
    r"""The customer's Stripe customer ID. This is useful for attributing recurring sale events to the partner who referred the customer."""
    country: NotRequired[Nullable[str]]
    r"""Country of the customer."""
    sales: NotRequired[Nullable[float]]
    r"""Total number of sales for the customer."""
    sale_amount: NotRequired[Nullable[float]]
    r"""Total amount of sales for the customer."""
    first_sale_at: NotRequired[Nullable[str]]
    r"""The date the customer made their first sale. Useful for calculating the time to first sale and LTV."""
    subscription_canceled_at: NotRequired[Nullable[str]]
    r"""The date the customer canceled their subscription. Useful for calculating LTV and churn rate."""


class UpdateCommissionCustomer(BaseModel):
    id: str
    r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""

    name: str
    r"""Name of the customer."""

    external_id: Annotated[str, pydantic.Field(alias="externalId")]
    r"""Unique identifier for the customer in the client's app."""

    created_at: Annotated[str, pydantic.Field(alias="createdAt")]
    r"""The date the customer was created (usually the signup date or trial start date)."""

    email: OptionalNullable[str] = UNSET
    r"""Email of the customer."""

    avatar: OptionalNullable[str] = UNSET
    r"""Avatar URL of the customer."""

    stripe_customer_id: Annotated[
        OptionalNullable[str], pydantic.Field(alias="stripeCustomerId")
    ] = UNSET
    r"""The customer's Stripe customer ID. This is useful for attributing recurring sale events to the partner who referred the customer."""

    country: OptionalNullable[str] = UNSET
    r"""Country of the customer."""

    sales: OptionalNullable[float] = UNSET
    r"""Total number of sales for the customer."""

    sale_amount: Annotated[
        OptionalNullable[float], pydantic.Field(alias="saleAmount")
    ] = UNSET
    r"""Total amount of sales for the customer."""

    first_sale_at: Annotated[
        OptionalNullable[str], pydantic.Field(alias="firstSaleAt")
    ] = UNSET
    r"""The date the customer made their first sale. Useful for calculating the time to first sale and LTV."""

    subscription_canceled_at: Annotated[
        OptionalNullable[str], pydantic.Field(alias="subscriptionCanceledAt")
    ] = UNSET
    r"""The date the customer canceled their subscription. Useful for calculating LTV and churn rate."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "email",
                "avatar",
                "stripeCustomerId",
                "country",
                "sales",
                "saleAmount",
                "firstSaleAt",
                "subscriptionCanceledAt",
            ]
        )
        nullable_fields = set(
            [
                "email",
                "avatar",
                "stripeCustomerId",
                "country",
                "sales",
                "saleAmount",
                "firstSaleAt",
                "subscriptionCanceledAt",
            ]
        )
        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}))  # 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 UpdateCommissionResponseBodyTypedDict(TypedDict):
    r"""The updated commission."""

    id: str
    r"""The commission's unique ID on Dub."""
    amount: float
    earnings: float
    currency: str
    status: UpdateCommissionStatus
    invoice_id: Nullable[str]
    description: Nullable[str]
    quantity: float
    created_at: str
    updated_at: str
    partner: UpdateCommissionPartnerTypedDict
    type: NotRequired[UpdateCommissionType]
    user_id: NotRequired[Nullable[str]]
    r"""The user who created the manual commission."""
    customer: NotRequired[Nullable[UpdateCommissionCustomerTypedDict]]


class UpdateCommissionResponseBody(BaseModel):
    r"""The updated commission."""

    id: str
    r"""The commission's unique ID on Dub."""

    amount: float

    earnings: float

    currency: str

    status: UpdateCommissionStatus

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

    description: Nullable[str]

    quantity: float

    created_at: Annotated[str, pydantic.Field(alias="createdAt")]

    updated_at: Annotated[str, pydantic.Field(alias="updatedAt")]

    partner: UpdateCommissionPartner

    type: Optional[UpdateCommissionType] = None

    user_id: Annotated[OptionalNullable[str], pydantic.Field(alias="userId")] = UNSET
    r"""The user who created the manual commission."""

    customer: OptionalNullable[UpdateCommissionCustomer] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["type", "userId", "customer"])
        nullable_fields = set(["invoiceId", "description", "userId", "customer"])
        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}))  # 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
