"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
# @generated-id: 744267ac80cf

from __future__ import annotations
from .amount import Amount, AmountTypedDict
from .metadata import Metadata, MetadataTypedDict
from .mode import Mode
from .subscription_method_response import SubscriptionMethodResponse
from .url import URL, URLTypedDict
from .url_nullable import URLNullable, URLNullableTypedDict
from enum import Enum
from mollie import models, utils
from mollie.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
import pydantic
from pydantic import field_serializer, model_serializer
from typing import Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class SubscriptionResponseStatus(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""The subscription's current status is directly related to the status of the underlying customer or mandate that is
    enabling the subscription.
    """

    PENDING = "pending"
    ACTIVE = "active"
    CANCELED = "canceled"
    SUSPENDED = "suspended"
    COMPLETED = "completed"


class SubscriptionResponseApplicationFeeTypedDict(TypedDict):
    r"""With Mollie Connect you can charge fees on payments that your app is processing on behalf of other Mollie
    merchants.

    Setting an application fee on the subscription will ensure this fee is charged on each individual payment.

    Refer to the `applicationFee` parameter on the [Get payment endpoint](get-payment) documentation for more
    information.
    """

    amount: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    description: str


class SubscriptionResponseApplicationFee(BaseModel):
    r"""With Mollie Connect you can charge fees on payments that your app is processing on behalf of other Mollie
    merchants.

    Setting an application fee on the subscription will ensure this fee is charged on each individual payment.

    Refer to the `applicationFee` parameter on the [Get payment endpoint](get-payment) documentation for more
    information.
    """

    amount: Amount
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    description: str


class SubscriptionResponseLinksTypedDict(TypedDict):
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""

    self_: URLTypedDict
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    customer: Nullable[URLNullableTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    profile: Nullable[URLNullableTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    documentation: URLTypedDict
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    mandate: NotRequired[Nullable[URLNullableTypedDict]]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    payments: NotRequired[Nullable[URLNullableTypedDict]]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""


class SubscriptionResponseLinks(BaseModel):
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""

    self_: Annotated[URL, pydantic.Field(alias="self")]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    customer: Nullable[URLNullable]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    profile: Nullable[URLNullable]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    documentation: URL
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    mandate: OptionalNullable[URLNullable] = UNSET
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    payments: OptionalNullable[URLNullable] = UNSET
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["mandate", "payments"])
        nullable_fields = set(["customer", "mandate", "profile", "payments"])
        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


class SubscriptionResponseTypedDict(TypedDict):
    resource: str
    r"""Indicates the response contains a subscription object. Will always contain the string `subscription` for this
    endpoint.
    """
    id: str
    r"""The identifier uniquely referring to this subscription. Example: `sub_rVKGtNd6s3`."""
    mode: Mode
    r"""Whether this entity was created in live mode or in test mode."""
    status: SubscriptionResponseStatus
    amount: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""
    times: Nullable[int]
    r"""Total number of payments for the subscription. Once this number of payments is reached, the subscription is
    considered completed.

    Test mode subscriptions will get canceled automatically after 10 payments.
    """
    times_remaining: Nullable[int]
    r"""Number of payments left for the subscription."""
    interval: str
    r"""Interval to wait between payments, for example `1 month` or `14 days`.

    The maximum interval is one year (`12 months`, `52 weeks`, or `365 days`).

    Possible values: `... days`, `... weeks`, `... months`.
    """
    start_date: str
    r"""The start date of the subscription in `YYYY-MM-DD` format."""
    description: str
    r"""The subscription's description will be used as the description of the resulting individual payments and so showing
    up on the bank statement of the consumer.

    **Please note:** the description needs to be unique for the Customer in case it has multiple active subscriptions.
    """
    method: Nullable[SubscriptionMethodResponse]
    r"""The payment method used for this subscription. If omitted, any of the customer's valid mandates may be used."""
    metadata: Nullable[MetadataTypedDict]
    r"""Provide any data you like, for example a string or a JSON object. We will save the data alongside the entity. Whenever
    you fetch the entity with our API, we will also include the metadata. You can use up to approximately 1kB.
    """
    webhook_url: Nullable[str]
    r"""We will call this URL for any payment status changes of payments resulting from this subscription.

    This webhook will receive **all** events for the subscription's payments. This may include payment failures as
    well. Be sure to verify the payment's subscription ID and its status.
    """
    customer_id: str
    r"""The customer this subscription belongs to."""
    created_at: str
    r"""The entity's date and time of creation, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."""
    links: SubscriptionResponseLinksTypedDict
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""
    next_payment_date: NotRequired[Nullable[str]]
    r"""The date of the next scheduled payment in `YYYY-MM-DD` format. If the subscription has been completed or canceled,
    this parameter will not be returned.
    """
    application_fee: NotRequired[SubscriptionResponseApplicationFeeTypedDict]
    r"""With Mollie Connect you can charge fees on payments that your app is processing on behalf of other Mollie
    merchants.

    Setting an application fee on the subscription will ensure this fee is charged on each individual payment.

    Refer to the `applicationFee` parameter on the [Get payment endpoint](get-payment) documentation for more
    information.
    """
    mandate_id: NotRequired[str]
    canceled_at: NotRequired[Nullable[str]]
    r"""The subscription's date and time of cancellation, in ISO 8601 format. This parameter is omitted if the
    subscription is not canceled (yet).
    """


class SubscriptionResponse(BaseModel):
    resource: str
    r"""Indicates the response contains a subscription object. Will always contain the string `subscription` for this
    endpoint.
    """

    id: str
    r"""The identifier uniquely referring to this subscription. Example: `sub_rVKGtNd6s3`."""

    mode: Mode
    r"""Whether this entity was created in live mode or in test mode."""

    status: SubscriptionResponseStatus

    amount: Amount
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""

    times: Nullable[int]
    r"""Total number of payments for the subscription. Once this number of payments is reached, the subscription is
    considered completed.

    Test mode subscriptions will get canceled automatically after 10 payments.
    """

    times_remaining: Annotated[Nullable[int], pydantic.Field(alias="timesRemaining")]
    r"""Number of payments left for the subscription."""

    interval: str
    r"""Interval to wait between payments, for example `1 month` or `14 days`.

    The maximum interval is one year (`12 months`, `52 weeks`, or `365 days`).

    Possible values: `... days`, `... weeks`, `... months`.
    """

    start_date: Annotated[str, pydantic.Field(alias="startDate")]
    r"""The start date of the subscription in `YYYY-MM-DD` format."""

    description: str
    r"""The subscription's description will be used as the description of the resulting individual payments and so showing
    up on the bank statement of the consumer.

    **Please note:** the description needs to be unique for the Customer in case it has multiple active subscriptions.
    """

    method: Nullable[SubscriptionMethodResponse]
    r"""The payment method used for this subscription. If omitted, any of the customer's valid mandates may be used."""

    metadata: Nullable[Metadata]
    r"""Provide any data you like, for example a string or a JSON object. We will save the data alongside the entity. Whenever
    you fetch the entity with our API, we will also include the metadata. You can use up to approximately 1kB.
    """

    webhook_url: Annotated[Nullable[str], pydantic.Field(alias="webhookUrl")]
    r"""We will call this URL for any payment status changes of payments resulting from this subscription.

    This webhook will receive **all** events for the subscription's payments. This may include payment failures as
    well. Be sure to verify the payment's subscription ID and its status.
    """

    customer_id: Annotated[str, pydantic.Field(alias="customerId")]
    r"""The customer this subscription belongs to."""

    created_at: Annotated[str, pydantic.Field(alias="createdAt")]
    r"""The entity's date and time of creation, in [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format."""

    links: Annotated[SubscriptionResponseLinks, pydantic.Field(alias="_links")]
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""

    next_payment_date: Annotated[
        OptionalNullable[str], pydantic.Field(alias="nextPaymentDate")
    ] = UNSET
    r"""The date of the next scheduled payment in `YYYY-MM-DD` format. If the subscription has been completed or canceled,
    this parameter will not be returned.
    """

    application_fee: Annotated[
        Optional[SubscriptionResponseApplicationFee],
        pydantic.Field(alias="applicationFee"),
    ] = None
    r"""With Mollie Connect you can charge fees on payments that your app is processing on behalf of other Mollie
    merchants.

    Setting an application fee on the subscription will ensure this fee is charged on each individual payment.

    Refer to the `applicationFee` parameter on the [Get payment endpoint](get-payment) documentation for more
    information.
    """

    mandate_id: Annotated[Optional[str], pydantic.Field(alias="mandateId")] = None

    canceled_at: Annotated[
        OptionalNullable[str], pydantic.Field(alias="canceledAt")
    ] = UNSET
    r"""The subscription's date and time of cancellation, in ISO 8601 format. This parameter is omitted if the
    subscription is not canceled (yet).
    """

    @field_serializer("mode")
    def serialize_mode(self, value):
        if isinstance(value, str):
            try:
                return models.Mode(value)
            except ValueError:
                return value
        return value

    @field_serializer("status")
    def serialize_status(self, value):
        if isinstance(value, str):
            try:
                return models.SubscriptionResponseStatus(value)
            except ValueError:
                return value
        return value

    @field_serializer("method")
    def serialize_method(self, value):
        if isinstance(value, str):
            try:
                return models.SubscriptionMethodResponse(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            ["nextPaymentDate", "applicationFee", "mandateId", "canceledAt"]
        )
        nullable_fields = set(
            [
                "times",
                "timesRemaining",
                "nextPaymentDate",
                "method",
                "metadata",
                "webhookUrl",
                "canceledAt",
            ]
        )
        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:
    SubscriptionResponseLinks.model_rebuild()
except NameError:
    pass
try:
    SubscriptionResponse.model_rebuild()
except NameError:
    pass
