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

from __future__ import annotations
from datetime import datetime
from paygentic_sdk.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
import pydantic
from pydantic import model_serializer
from typing import Dict, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class CreateSubscriptionAddressTypedDict(TypedDict):
    r"""Address is required for tax calculation. Must include: country (ISO 3166-1 alpha-2) and zipCode. The state/region field is required and validated for US/CA addresses only (custom validation in API logic). Postal code format is not validated but will be normalized."""

    country: str
    r"""2 character ISO 3166 country code"""
    zip_code: str
    line1: NotRequired[str]
    line2: NotRequired[str]
    city: NotRequired[str]
    state: NotRequired[str]


class CreateSubscriptionAddress(BaseModel):
    r"""Address is required for tax calculation. Must include: country (ISO 3166-1 alpha-2) and zipCode. The state/region field is required and validated for US/CA addresses only (custom validation in API logic). Postal code format is not validated but will be normalized."""

    country: str
    r"""2 character ISO 3166 country code"""

    zip_code: Annotated[str, pydantic.Field(alias="zipCode")]

    line1: Optional[str] = None

    line2: Optional[str] = None

    city: Optional[str] = None

    state: Optional[str] = None

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["line1", "line2", "city", "state"])
        serialized = handler(self)
        m = {}

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

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class CreateSubscriptionCustomerTypedDict(TypedDict):
    r"""Fields to create a new customer and consumer. Will use an existing consumer if one exists with the same email address. Required if `customerId` is not provided. Address with complete tax information (country, state, zipCode) is required for tax calculation when using Paygentic Tax."""

    name: str
    email: str
    address: CreateSubscriptionAddressTypedDict
    phone: NotRequired[str]
    tax_rates: NotRequired[Dict[str, float]]
    r"""An object mapping plan IDs, metric IDs, or 'default' to a tax rate percentage (e.g., 13 for 13%)"""


class CreateSubscriptionCustomer(BaseModel):
    r"""Fields to create a new customer and consumer. Will use an existing consumer if one exists with the same email address. Required if `customerId` is not provided. Address with complete tax information (country, state, zipCode) is required for tax calculation when using Paygentic Tax."""

    name: str

    email: str

    address: CreateSubscriptionAddress

    phone: Optional[str] = None

    tax_rates: Annotated[
        Optional[Dict[str, float]], pydantic.Field(alias="taxRates")
    ] = None
    r"""An object mapping plan IDs, metric IDs, or 'default' to a tax rate percentage (e.g., 13 for 13%)"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["phone", "taxRates"])
        serialized = handler(self)
        m = {}

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

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class RedirectUrlsTypedDict(TypedDict):
    r"""Optional redirect URLs after payment completion or failure. If not provided, uses default platform behavior."""

    on_success: NotRequired[str]
    r"""Redirect destination after successful payment. Sample values: 'https://app.example.com/success', 'https://dashboard.company.com/welcome', 'https://portal.startup.io/complete'"""
    on_failure: NotRequired[str]
    r"""Redirect destination after failed payment. Sample values: 'https://app.example.com/payment-failed', 'https://dashboard.company.com/retry', 'https://portal.startup.io/error'"""


class RedirectUrls(BaseModel):
    r"""Optional redirect URLs after payment completion or failure. If not provided, uses default platform behavior."""

    on_success: Annotated[Optional[str], pydantic.Field(alias="onSuccess")] = None
    r"""Redirect destination after successful payment. Sample values: 'https://app.example.com/success', 'https://dashboard.company.com/welcome', 'https://portal.startup.io/complete'"""

    on_failure: Annotated[Optional[str], pydantic.Field(alias="onFailure")] = None
    r"""Redirect destination after failed payment. Sample values: 'https://app.example.com/payment-failed', 'https://dashboard.company.com/retry', 'https://portal.startup.io/error'"""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["onSuccess", "onFailure"])
        serialized = handler(self)
        m = {}

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

            if val != UNSET_SENTINEL:
                if val is not None or k not in optional_fields:
                    m[k] = val

        return m


class CreateSubscriptionRequestTypedDict(TypedDict):
    name: str
    r"""Subscription identifier combining customer and service details. Sample values: 'TechCorp - LLM API Access', 'Analytics Co - Data Platform Enterprise', 'StartupXYZ - Image Generation Service', 'Enterprise Inc - ML Training Platform'"""
    plan_id: str
    r"""Unique identifier for a plan"""
    started_at: datetime
    r"""Subscription activation timestamp in ISO 8601 format. Sample values: '2024-01-15T10:30:00Z', '2024-02-01T00:00:00Z'"""
    auto_charge: NotRequired[bool]
    r"""Enable automatic charging of invoices using stored payment methods. When true, invoices will be automatically paid using off-session payment. Defaults to false."""
    tax_exempt: NotRequired[bool]
    r"""When true, forces tax rate to 0%. Use for customers with verified tax-exempt status."""
    customer: NotRequired[CreateSubscriptionCustomerTypedDict]
    r"""Fields to create a new customer and consumer. Will use an existing consumer if one exists with the same email address. Required if `customerId` is not provided. Address with complete tax information (country, state, zipCode) is required for tax calculation when using Paygentic Tax."""
    customer_id: NotRequired[str]
    r"""Unique identifier for a customer"""
    ending_at: NotRequired[datetime]
    r"""Subscription expiration timestamp in ISO 8601 format. Sample values: '2024-12-31T23:59:59Z', '2025-01-15T10:30:00Z'. Omit for indefinite subscriptions."""
    prefund_amount: NotRequired[str]
    r"""@deprecated Use minimumAccountBalance instead. Required initial wallet deposit amount. Sample values: '200.00' requires $200 prepaid balance for metered LLM usage, '1000.00' requires $1000 prepaid credits for data processing services, '50.00' requires $50 minimum for API call consumption"""
    minimum_account_balance: NotRequired[str]
    r"""Minimum wallet balance requirement in decimal dollars (e.g., '100.00'). Can be set to '0' to disable. The system will calculate the difference between this minimum and the customer's current balance, charging only what's needed to reach the minimum. If the customer already has sufficient balance, no charge is made. Note: If the calculated charge amount is below payment processor minimums (typically $1.00), it will be automatically adjusted upward to meet the minimum requirement. Sample values: '200.00' requires minimum $200 balance for metered LLM usage, '1000.00' requires minimum $1000 balance for data processing services"""
    redirect_urls: NotRequired[RedirectUrlsTypedDict]
    r"""Optional redirect URLs after payment completion or failure. If not provided, uses default platform behavior."""
    test_clock_id: NotRequired[str]
    r"""Test clock identifier for simulating time-based billing scenarios. Sample values: 'tc_abc123xyz', 'tc_789def456'. Restricted to non-production environments (local, dev, sandbox). Must belong to the same merchant organization."""
    renewal_reminder_enabled: NotRequired[Nullable[bool]]
    r"""Override plan setting for renewal reminder emails. When set, this subscription's setting takes precedence over the plan default. Set to true to enable reminders, false to disable, or null/omit to use plan default."""
    renewal_reminder_days: NotRequired[Nullable[int]]
    r"""Override plan setting for number of days before renewal to send the reminder. Only used if renewalReminderEnabled is true (or inherited from plan). Set to null to use plan default."""
    session_expiry_minutes: NotRequired[float]
    r"""Number of minutes until the payment session expires. Defaults to 240 minutes (4 hours) if not provided."""


class CreateSubscriptionRequest(BaseModel):
    name: str
    r"""Subscription identifier combining customer and service details. Sample values: 'TechCorp - LLM API Access', 'Analytics Co - Data Platform Enterprise', 'StartupXYZ - Image Generation Service', 'Enterprise Inc - ML Training Platform'"""

    plan_id: Annotated[str, pydantic.Field(alias="planId")]
    r"""Unique identifier for a plan"""

    started_at: Annotated[datetime, pydantic.Field(alias="startedAt")]
    r"""Subscription activation timestamp in ISO 8601 format. Sample values: '2024-01-15T10:30:00Z', '2024-02-01T00:00:00Z'"""

    auto_charge: Annotated[Optional[bool], pydantic.Field(alias="autoCharge")] = False
    r"""Enable automatic charging of invoices using stored payment methods. When true, invoices will be automatically paid using off-session payment. Defaults to false."""

    tax_exempt: Annotated[Optional[bool], pydantic.Field(alias="taxExempt")] = False
    r"""When true, forces tax rate to 0%. Use for customers with verified tax-exempt status."""

    customer: Optional[CreateSubscriptionCustomer] = None
    r"""Fields to create a new customer and consumer. Will use an existing consumer if one exists with the same email address. Required if `customerId` is not provided. Address with complete tax information (country, state, zipCode) is required for tax calculation when using Paygentic Tax."""

    customer_id: Annotated[Optional[str], pydantic.Field(alias="customerId")] = None
    r"""Unique identifier for a customer"""

    ending_at: Annotated[Optional[datetime], pydantic.Field(alias="endingAt")] = None
    r"""Subscription expiration timestamp in ISO 8601 format. Sample values: '2024-12-31T23:59:59Z', '2025-01-15T10:30:00Z'. Omit for indefinite subscriptions."""

    prefund_amount: Annotated[Optional[str], pydantic.Field(alias="prefundAmount")] = (
        None
    )
    r"""@deprecated Use minimumAccountBalance instead. Required initial wallet deposit amount. Sample values: '200.00' requires $200 prepaid balance for metered LLM usage, '1000.00' requires $1000 prepaid credits for data processing services, '50.00' requires $50 minimum for API call consumption"""

    minimum_account_balance: Annotated[
        Optional[str], pydantic.Field(alias="minimumAccountBalance")
    ] = None
    r"""Minimum wallet balance requirement in decimal dollars (e.g., '100.00'). Can be set to '0' to disable. The system will calculate the difference between this minimum and the customer's current balance, charging only what's needed to reach the minimum. If the customer already has sufficient balance, no charge is made. Note: If the calculated charge amount is below payment processor minimums (typically $1.00), it will be automatically adjusted upward to meet the minimum requirement. Sample values: '200.00' requires minimum $200 balance for metered LLM usage, '1000.00' requires minimum $1000 balance for data processing services"""

    redirect_urls: Annotated[
        Optional[RedirectUrls], pydantic.Field(alias="redirectUrls")
    ] = None
    r"""Optional redirect URLs after payment completion or failure. If not provided, uses default platform behavior."""

    test_clock_id: Annotated[Optional[str], pydantic.Field(alias="testClockId")] = None
    r"""Test clock identifier for simulating time-based billing scenarios. Sample values: 'tc_abc123xyz', 'tc_789def456'. Restricted to non-production environments (local, dev, sandbox). Must belong to the same merchant organization."""

    renewal_reminder_enabled: Annotated[
        OptionalNullable[bool], pydantic.Field(alias="renewalReminderEnabled")
    ] = UNSET
    r"""Override plan setting for renewal reminder emails. When set, this subscription's setting takes precedence over the plan default. Set to true to enable reminders, false to disable, or null/omit to use plan default."""

    renewal_reminder_days: Annotated[
        OptionalNullable[int], pydantic.Field(alias="renewalReminderDays")
    ] = UNSET
    r"""Override plan setting for number of days before renewal to send the reminder. Only used if renewalReminderEnabled is true (or inherited from plan). Set to null to use plan default."""

    session_expiry_minutes: Annotated[
        Optional[float], pydantic.Field(alias="sessionExpiryMinutes")
    ] = None
    r"""Number of minutes until the payment session expires. Defaults to 240 minutes (4 hours) if not provided."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "autoCharge",
                "taxExempt",
                "customer",
                "customerId",
                "endingAt",
                "prefundAmount",
                "minimumAccountBalance",
                "redirectUrls",
                "testClockId",
                "renewalReminderEnabled",
                "renewalReminderDays",
                "sessionExpiryMinutes",
            ]
        )
        nullable_fields = set(["renewalReminderEnabled", "renewalReminderDays"])
        serialized = handler(self)
        m = {}

        for n, f in type(self).model_fields.items():
            k = f.alias or n
            val = serialized.get(k, serialized.get(n))
            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


try:
    CreateSubscriptionAddress.model_rebuild()
except NameError:
    pass
try:
    CreateSubscriptionCustomer.model_rebuild()
except NameError:
    pass
try:
    RedirectUrls.model_rebuild()
except NameError:
    pass
try:
    CreateSubscriptionRequest.model_rebuild()
except NameError:
    pass
