"""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, QueryParamMetadata
from enum import Enum
import pydantic
from pydantic import model_serializer
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class ListPayoutsQueryParamStatus(str, Enum):
    r"""Filter the list of payouts by their corresponding status."""

    PENDING = "pending"
    PROCESSING = "processing"
    PROCESSED = "processed"
    SENT = "sent"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELED = "canceled"


class ListPayoutsQueryParamSortBy(str, Enum):
    r"""The field to sort the list of payouts by."""

    AMOUNT = "amount"
    INITIATED_AT = "initiatedAt"
    PAID_AT = "paidAt"


class ListPayoutsQueryParamSortOrder(str, Enum):
    r"""The sort order for the list of payouts."""

    ASC = "asc"
    DESC = "desc"


class ListPayoutsRequestTypedDict(TypedDict):
    status: NotRequired[ListPayoutsQueryParamStatus]
    r"""Filter the list of payouts by their corresponding status."""
    partner_id: NotRequired[str]
    r"""Filter the list of payouts by the associated partner. When specified, takes precedence over `tenantId`."""
    tenant_id: NotRequired[str]
    r"""Filter the list of payouts by the associated partner's `tenantId` (their unique ID within your database)."""
    invoice_id: NotRequired[str]
    r"""Filter the list of payouts by invoice ID (the unique ID of the invoice you receive for each batch payout you process on Dub). Pending payouts will not have an invoice ID."""
    sort_by: NotRequired[ListPayoutsQueryParamSortBy]
    r"""The field to sort the list of payouts by."""
    sort_order: NotRequired[ListPayoutsQueryParamSortOrder]
    r"""The sort order for the list of payouts."""
    page: NotRequired[float]
    r"""The page number for pagination."""
    page_size: NotRequired[float]
    r"""The number of items per page."""


class ListPayoutsRequest(BaseModel):
    status: Annotated[
        Optional[ListPayoutsQueryParamStatus],
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter the list of payouts by their corresponding status."""

    partner_id: Annotated[
        Optional[str],
        pydantic.Field(alias="partnerId"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter the list of payouts by the associated partner. When specified, takes precedence over `tenantId`."""

    tenant_id: Annotated[
        Optional[str],
        pydantic.Field(alias="tenantId"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter the list of payouts by the associated partner's `tenantId` (their unique ID within your database)."""

    invoice_id: Annotated[
        Optional[str],
        pydantic.Field(alias="invoiceId"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = None
    r"""Filter the list of payouts by invoice ID (the unique ID of the invoice you receive for each batch payout you process on Dub). Pending payouts will not have an invoice ID."""

    sort_by: Annotated[
        Optional[ListPayoutsQueryParamSortBy],
        pydantic.Field(alias="sortBy"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = ListPayoutsQueryParamSortBy.AMOUNT
    r"""The field to sort the list of payouts by."""

    sort_order: Annotated[
        Optional[ListPayoutsQueryParamSortOrder],
        pydantic.Field(alias="sortOrder"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = ListPayoutsQueryParamSortOrder.DESC
    r"""The sort order for the list of payouts."""

    page: Annotated[
        Optional[float],
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = 1
    r"""The page number for pagination."""

    page_size: Annotated[
        Optional[float],
        pydantic.Field(alias="pageSize"),
        FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
    ] = 100
    r"""The number of items per page."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "status",
                "partnerId",
                "tenantId",
                "invoiceId",
                "sortBy",
                "sortOrder",
                "page",
                "pageSize",
            ]
        )
        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 ListPayoutsStatus(str, Enum):
    PENDING = "pending"
    PROCESSING = "processing"
    PROCESSED = "processed"
    SENT = "sent"
    COMPLETED = "completed"
    FAILED = "failed"
    CANCELED = "canceled"


class ListPayoutsMode(str, Enum):
    INTERNAL = "internal"
    EXTERNAL = "external"


class ProfileType(str, Enum):
    r"""The partner's profile type on Dub."""

    INDIVIDUAL = "individual"
    COMPANY = "company"


class InvoiceSettingsTypedDict(TypedDict):
    r"""The partner's invoice settings."""

    address: NotRequired[Nullable[str]]
    tax_id: NotRequired[Nullable[str]]


class InvoiceSettings(BaseModel):
    r"""The partner's invoice settings."""

    address: OptionalNullable[str] = UNSET

    tax_id: Annotated[OptionalNullable[str], pydantic.Field(alias="taxId")] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["address", "taxId"])
        nullable_fields = set(["address", "taxId"])
        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 MonthlyTraffic(str, Enum):
    r"""The partner's monthly traffic."""

    ZERO_TO_ONE_THOUSAND = "ZeroToOneThousand"
    ONE_THOUSAND_TO_TEN_THOUSAND = "OneThousandToTenThousand"
    TEN_THOUSAND_TO_FIFTY_THOUSAND = "TenThousandToFiftyThousand"
    FIFTY_THOUSAND_TO_ONE_HUNDRED_THOUSAND = "FiftyThousandToOneHundredThousand"
    ONE_HUNDRED_THOUSAND_PLUS = "OneHundredThousandPlus"


class IndustryInterests(str, Enum):
    SAA_S = "SaaS"
    DEV_TOOL = "DevTool"
    AI = "AI"
    CREATIVE_AND_DESIGN = "Creative_And_Design"
    PRODUCTIVITY_SOFTWARE = "Productivity_Software"
    MARKETING = "Marketing"
    GAMING = "Gaming"
    FINANCE = "Finance"
    SALES = "Sales"
    ECOMMERCE = "Ecommerce"
    CUSTOMER_SERVICE_AND_SUPPORT = "Customer_Service_And_Support"
    CONTENT_MANAGEMENT = "Content_Management"
    HUMAN_RESOURCES = "Human_Resources"
    SECURITY = "Security"
    ANALYTICS_AND_DATA = "Analytics_And_Data"
    SOCIAL_MEDIA = "Social_Media"
    CONSUMER_TECH = "Consumer_Tech"
    EDUCATION_AND_LEARNING = "Education_And_Learning"
    HEALTH_AND_FITNESS = "Health_And_Fitness"
    FOOD_AND_BEVERAGE = "Food_And_Beverage"
    TRAVEL_AND_LIFESTYLE = "Travel_And_Lifestyle"
    ENTERTAINMENT_AND_MEDIA = "Entertainment_And_Media"
    SPORTS = "Sports"
    SCIENCE_AND_ENGINEERING = "Science_And_Engineering"


class PreferredEarningStructures(str, Enum):
    REVENUE_SHARE = "Revenue_Share"
    PER_LEAD = "Per_Lead"
    PER_SALE = "Per_Sale"
    PER_CLICK = "Per_Click"
    ONE_TIME_PAYMENT = "One_Time_Payment"


class SalesChannels(str, Enum):
    BLOGS = "Blogs"
    COUPONS = "Coupons"
    DIRECT_RESELLING = "Direct_Reselling"
    NEWSLETTERS = "Newsletters"
    SOCIAL_MEDIA = "Social_Media"
    EVENTS = "Events"
    COMPANY_REFERRALS = "Company_Referrals"


class ListPayoutsPartnerTypedDict(TypedDict):
    id: str
    r"""The partner's unique ID on Dub."""
    name: str
    r"""The partner's full legal name."""
    company_name: Nullable[str]
    r"""If the partner profile type is a company, this is the partner's legal company name."""
    profile_type: ProfileType
    r"""The partner's profile type on Dub."""
    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."""
    country: Nullable[str]
    r"""The partner's country (required for tax purposes)."""
    stripe_connect_id: Nullable[str]
    r"""The partner's Stripe Connect ID (for receiving payouts via Stripe)."""
    paypal_email: Nullable[str]
    r"""The partner's PayPal email (for receiving payouts via PayPal)."""
    payouts_enabled_at: Nullable[str]
    r"""The date when the partner enabled payouts."""
    invoice_settings: Nullable[InvoiceSettingsTypedDict]
    r"""The partner's invoice settings."""
    created_at: str
    r"""The date when the partner was created on Dub."""
    discoverable_at: Nullable[str]
    r"""The date when the partner was added to the partner network."""
    trusted_at: Nullable[str]
    r"""The date when the partner received the trusted badge in the partner network."""
    tenant_id: Nullable[str]
    description: NotRequired[Nullable[str]]
    r"""A brief description of the partner and their background."""
    website: NotRequired[Nullable[str]]
    r"""The partner's website URL (including the https protocol)."""
    youtube: NotRequired[Nullable[str]]
    r"""The partner's YouTube channel username (e.g. `johndoe`)."""
    twitter: NotRequired[Nullable[str]]
    r"""The partner's Twitter username (e.g. `johndoe`)."""
    linkedin: NotRequired[Nullable[str]]
    r"""The partner's LinkedIn username (e.g. `johndoe`)."""
    instagram: NotRequired[Nullable[str]]
    r"""The partner's Instagram username (e.g. `johndoe`)."""
    tiktok: NotRequired[Nullable[str]]
    r"""The partner's TikTok username (e.g. `johndoe`)."""
    monthly_traffic: NotRequired[Nullable[MonthlyTraffic]]
    r"""The partner's monthly traffic."""
    industry_interests: NotRequired[List[IndustryInterests]]
    r"""The partner's industry interests."""
    preferred_earning_structures: NotRequired[List[PreferredEarningStructures]]
    r"""The partner's preferred earning structures."""
    sales_channels: NotRequired[List[SalesChannels]]
    r"""The partner's sales channels."""


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

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

    company_name: Annotated[Nullable[str], pydantic.Field(alias="companyName")]
    r"""If the partner profile type is a company, this is the partner's legal company name."""

    profile_type: Annotated[ProfileType, pydantic.Field(alias="profileType")]
    r"""The partner's profile type on Dub."""

    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."""

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

    stripe_connect_id: Annotated[Nullable[str], pydantic.Field(alias="stripeConnectId")]
    r"""The partner's Stripe Connect ID (for receiving payouts via Stripe)."""

    paypal_email: Annotated[Nullable[str], pydantic.Field(alias="paypalEmail")]
    r"""The partner's PayPal email (for receiving payouts via PayPal)."""

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

    invoice_settings: Annotated[
        Nullable[InvoiceSettings], pydantic.Field(alias="invoiceSettings")
    ]
    r"""The partner's invoice settings."""

    created_at: Annotated[str, pydantic.Field(alias="createdAt")]
    r"""The date when the partner was created on Dub."""

    discoverable_at: Annotated[Nullable[str], pydantic.Field(alias="discoverableAt")]
    r"""The date when the partner was added to the partner network."""

    trusted_at: Annotated[Nullable[str], pydantic.Field(alias="trustedAt")]
    r"""The date when the partner received the trusted badge in the partner network."""

    tenant_id: Annotated[Nullable[str], pydantic.Field(alias="tenantId")]

    description: OptionalNullable[str] = UNSET
    r"""A brief description of the partner and their background."""

    website: OptionalNullable[str] = UNSET
    r"""The partner's website URL (including the https protocol)."""

    youtube: OptionalNullable[str] = UNSET
    r"""The partner's YouTube channel username (e.g. `johndoe`)."""

    twitter: OptionalNullable[str] = UNSET
    r"""The partner's Twitter username (e.g. `johndoe`)."""

    linkedin: OptionalNullable[str] = UNSET
    r"""The partner's LinkedIn username (e.g. `johndoe`)."""

    instagram: OptionalNullable[str] = UNSET
    r"""The partner's Instagram username (e.g. `johndoe`)."""

    tiktok: OptionalNullable[str] = UNSET
    r"""The partner's TikTok username (e.g. `johndoe`)."""

    monthly_traffic: Annotated[
        OptionalNullable[MonthlyTraffic], pydantic.Field(alias="monthlyTraffic")
    ] = UNSET
    r"""The partner's monthly traffic."""

    industry_interests: Annotated[
        Optional[List[IndustryInterests]], pydantic.Field(alias="industryInterests")
    ] = None
    r"""The partner's industry interests."""

    preferred_earning_structures: Annotated[
        Optional[List[PreferredEarningStructures]],
        pydantic.Field(alias="preferredEarningStructures"),
    ] = None
    r"""The partner's preferred earning structures."""

    sales_channels: Annotated[
        Optional[List[SalesChannels]], pydantic.Field(alias="salesChannels")
    ] = None
    r"""The partner's sales channels."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "description",
                "website",
                "youtube",
                "twitter",
                "linkedin",
                "instagram",
                "tiktok",
                "monthlyTraffic",
                "industryInterests",
                "preferredEarningStructures",
                "salesChannels",
            ]
        )
        nullable_fields = set(
            [
                "companyName",
                "email",
                "image",
                "description",
                "country",
                "stripeConnectId",
                "paypalEmail",
                "payoutsEnabledAt",
                "invoiceSettings",
                "discoverableAt",
                "trustedAt",
                "website",
                "youtube",
                "twitter",
                "linkedin",
                "instagram",
                "tiktok",
                "monthlyTraffic",
                "tenantId",
            ]
        )
        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 UserTypedDict(TypedDict):
    id: str
    name: Nullable[str]
    email: Nullable[str]
    image: Nullable[str]


class User(BaseModel):
    id: str

    name: Nullable[str]

    email: Nullable[str]

    image: Nullable[str]

    @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 ListPayoutsResponseBodyTypedDict(TypedDict):
    id: str
    invoice_id: Nullable[str]
    amount: float
    currency: str
    status: ListPayoutsStatus
    period_start: Nullable[str]
    period_end: Nullable[str]
    created_at: str
    initiated_at: Nullable[str]
    paid_at: Nullable[str]
    mode: Nullable[ListPayoutsMode]
    partner: ListPayoutsPartnerTypedDict
    description: NotRequired[Nullable[str]]
    failure_reason: NotRequired[Nullable[str]]
    user: NotRequired[Nullable[UserTypedDict]]


class ListPayoutsResponseBody(BaseModel):
    id: str

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

    amount: float

    currency: str

    status: ListPayoutsStatus

    period_start: Annotated[Nullable[str], pydantic.Field(alias="periodStart")]

    period_end: Annotated[Nullable[str], pydantic.Field(alias="periodEnd")]

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

    initiated_at: Annotated[Nullable[str], pydantic.Field(alias="initiatedAt")]

    paid_at: Annotated[Nullable[str], pydantic.Field(alias="paidAt")]

    mode: Nullable[ListPayoutsMode]

    partner: ListPayoutsPartner

    description: OptionalNullable[str] = UNSET

    failure_reason: Annotated[
        OptionalNullable[str], pydantic.Field(alias="failureReason")
    ] = UNSET

    user: OptionalNullable[User] = UNSET

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["description", "failureReason", "user"])
        nullable_fields = set(
            [
                "invoiceId",
                "description",
                "periodStart",
                "periodEnd",
                "initiatedAt",
                "paidAt",
                "failureReason",
                "mode",
                "user",
            ]
        )
        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
