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

from __future__ import annotations
from .airline import Airline, AirlineTypedDict
from .applepaypaymentmethodcreate import (
    ApplePayPaymentMethodCreate,
    ApplePayPaymentMethodCreateTypedDict,
)
from .browserinfo import BrowserInfo, BrowserInfoTypedDict
from .cardwithurlpaymentmethodcreate import (
    CardWithURLPaymentMethodCreate,
    CardWithURLPaymentMethodCreateTypedDict,
)
from .cartitem import CartItem, CartItemTypedDict
from .checkoutsessionwithurlpaymentmethodcreate import (
    CheckoutSessionWithURLPaymentMethodCreate,
    CheckoutSessionWithURLPaymentMethodCreateTypedDict,
)
from .clicktopayfpanpaymentmethodcreate import (
    ClickToPayFPANPaymentMethodCreate,
    ClickToPayFPANPaymentMethodCreateTypedDict,
)
from .clicktopaypaymentmethodcreate import (
    ClickToPayPaymentMethodCreate,
    ClickToPayPaymentMethodCreateTypedDict,
)
from .giftcardtokentransactioncreate import (
    GiftCardTokenTransactionCreate,
    GiftCardTokenTransactionCreateTypedDict,
)
from .giftcardtransactioncreate import (
    GiftCardTransactionCreate,
    GiftCardTransactionCreateTypedDict,
)
from .googlepayfpanpaymentmethodcreate import (
    GooglePayFPANPaymentMethodCreate,
    GooglePayFPANPaymentMethodCreateTypedDict,
)
from .googlepaypaymentmethodcreate import (
    GooglePayPaymentMethodCreate,
    GooglePayPaymentMethodCreateTypedDict,
)
from .guestbuyer_input import GuestBuyerInput, GuestBuyerInputTypedDict
from .networktokenpaymentmethodcreate import (
    NetworkTokenPaymentMethodCreate,
    NetworkTokenPaymentMethodCreateTypedDict,
)
from .recipient import Recipient, RecipientTypedDict
from .redirectpaymentmethodcreate import (
    RedirectPaymentMethodCreate,
    RedirectPaymentMethodCreateTypedDict,
)
from .statementdescriptor import StatementDescriptor, StatementDescriptorTypedDict
from .threedsecuredatav1 import ThreeDSecureDataV1, ThreeDSecureDataV1TypedDict
from .threedsecuredatav2 import ThreeDSecureDataV2, ThreeDSecureDataV2TypedDict
from .tokenpaymentmethodcreate import (
    TokenPaymentMethodCreate,
    TokenPaymentMethodCreateTypedDict,
)
from .transactionintent import TransactionIntent
from .transactionpaymentsource import TransactionPaymentSource
from gr4vy.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from gr4vy.utils import validate_open_enum
from pydantic import model_serializer
from pydantic.functional_validators import PlainValidator
from typing import Any, Dict, List, Optional, Union
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict


TransactionCreatePaymentMethodTypedDict = TypeAliasType(
    "TransactionCreatePaymentMethodTypedDict",
    Union[
        TokenPaymentMethodCreateTypedDict,
        CheckoutSessionWithURLPaymentMethodCreateTypedDict,
        RedirectPaymentMethodCreateTypedDict,
        ClickToPayPaymentMethodCreateTypedDict,
        CardWithURLPaymentMethodCreateTypedDict,
        ApplePayPaymentMethodCreateTypedDict,
        ClickToPayFPANPaymentMethodCreateTypedDict,
        GooglePayFPANPaymentMethodCreateTypedDict,
        GooglePayPaymentMethodCreateTypedDict,
        NetworkTokenPaymentMethodCreateTypedDict,
    ],
)
r"""The optional payment method to use for this transaction. This field is required if no `gift_cards` have been added."""


TransactionCreatePaymentMethod = TypeAliasType(
    "TransactionCreatePaymentMethod",
    Union[
        TokenPaymentMethodCreate,
        CheckoutSessionWithURLPaymentMethodCreate,
        RedirectPaymentMethodCreate,
        ClickToPayPaymentMethodCreate,
        CardWithURLPaymentMethodCreate,
        ApplePayPaymentMethodCreate,
        ClickToPayFPANPaymentMethodCreate,
        GooglePayFPANPaymentMethodCreate,
        GooglePayPaymentMethodCreate,
        NetworkTokenPaymentMethodCreate,
    ],
)
r"""The optional payment method to use for this transaction. This field is required if no `gift_cards` have been added."""


GiftCardUnionTypedDict = TypeAliasType(
    "GiftCardUnionTypedDict",
    Union[GiftCardTokenTransactionCreateTypedDict, GiftCardTransactionCreateTypedDict],
)


GiftCardUnion = TypeAliasType(
    "GiftCardUnion", Union[GiftCardTokenTransactionCreate, GiftCardTransactionCreate]
)


ThreeDSecureDataTypedDict = TypeAliasType(
    "ThreeDSecureDataTypedDict",
    Union[ThreeDSecureDataV2TypedDict, ThreeDSecureDataV1TypedDict],
)
r"""Pass through 3-D Secure data to support external 3-D Secure authorisation. If using an external 3-D Secure provider, you should not pass a `redirect_url` in the `payment_method` object for a transaction."""


ThreeDSecureData = TypeAliasType(
    "ThreeDSecureData", Union[ThreeDSecureDataV2, ThreeDSecureDataV1]
)
r"""Pass through 3-D Secure data to support external 3-D Secure authorisation. If using an external 3-D Secure provider, you should not pass a `redirect_url` in the `payment_method` object for a transaction."""


class TransactionCreateTypedDict(TypedDict):
    amount: int
    r"""The monetary amount for this transaction, in the smallest currency unit for the given currency, for example `1299` cents to create an authorization for `$12.99`. If the `intent` is set to `capture`, an amount greater than zero must be supplied. All gift card amounts are subtracted from this amount before the remainder is charged to the provided `payment_method`."""
    currency: str
    r"""A supported ISO 4217 currency code. For redirect requests, this value must match the one specified for `currency` in `payment_method`."""
    country: NotRequired[Nullable[str]]
    r"""The 2-letter ISO code of the country where the transaction is processed. This is also used to filter the payment services that can process the transaction. If this value is provided for redirect requests and it's not `null`, it must match the one specified for `country` in `payment_method`. Otherwise, the value specified for `country` in `payment_method` will be assumed implicitly."""
    payment_method: NotRequired[Nullable[TransactionCreatePaymentMethodTypedDict]]
    r"""The optional payment method to use for this transaction. This field is required if no `gift_cards` have been added."""
    buyer: NotRequired[Nullable[GuestBuyerInputTypedDict]]
    r"""Guest buyer details provided inline rather than creating a buyer resource beforehand and using the `buyer_id` or `buyer_external_identifier` keys. No buyer resource will be created on Gr4vy when used."""
    buyer_id: NotRequired[Nullable[str]]
    r"""The ID of the buyer to associate this payment method to. If this field is provided then the `buyer_external_identifier` field needs to be unset. If a stored payment method or gift card is provided, then the buyer for that payment method needs to match the buyer for this field."""
    buyer_external_identifier: NotRequired[Nullable[str]]
    r"""The `external_identifier` of the buyer to associate this payment method to. If this field is provided then the `buyer_id` field needs to be unset. If a stored payment method or gift card is provided, then the buyer for that payment method needs to match the buyer for this field."""
    gift_cards: NotRequired[Nullable[List[GiftCardUnionTypedDict]]]
    r"""The optional gift card(s) to use for this transaction. At least one gift card is required if no other `payment_method` has been added. By default, only a maximum limit of 10 gift cards may be used in a single transaction. Please contact our team to change this limit."""
    external_identifier: NotRequired[Nullable[str]]
    r"""An external identifier that can be used to match the transaction against your own records."""
    intent: NotRequired[TransactionIntent]
    store: NotRequired[bool]
    r"""Whether or not to also try and store the payment method with us so that it can be used again for future use. This is only supported for payment methods that support this feature. There are also a few restrictions on how the flag may be set:

    * The flag has to be set to `true` when the `payment_source` is set to `recurring` or `installment`, and `merchant_initiated` is set to `false`.
    * The flag has to be set to `false` (or not set) when using a previously vaulted payment method.
    """
    three_d_secure_data: NotRequired[Nullable[ThreeDSecureDataTypedDict]]
    r"""Pass through 3-D Secure data to support external 3-D Secure authorisation. If using an external 3-D Secure provider, you should not pass a `redirect_url` in the `payment_method` object for a transaction."""
    metadata: NotRequired[Nullable[Dict[str, str]]]
    r"""Any additional information about the transaction that you would like to store as key-value pairs. This data is passed to payment service providers that support it."""
    is_subsequent_payment: NotRequired[bool]
    r"""Indicates whether the transaction represents a subsequent payment coming from a setup recurring payment. Please note there are some restrictions on how this flag may be used.

    The flag can only be `false` (or not set) when the transaction meets one of the following criteria:

    * It is not `merchant_initiated`.
    * `payment_source` is set to `card_on_file`.

    The flag can only be set to `true` when the transaction meets one of the following criteria:
    * It is not `merchant_initiated`.
    * `payment_source` is set to `recurring` or `installment` and `merchant_initiated` is set to `true`.
    * `payment_source` is set to `card_on_file`.
    """
    merchant_initiated: NotRequired[bool]
    r"""Indicates whether the transaction was initiated by the merchant (true) or customer (false)."""
    payment_source: NotRequired[TransactionPaymentSource]
    r"""The way payment method information made it to this transaction."""
    airline: NotRequired[Nullable[AirlineTypedDict]]
    r"""The airline addendum data which describes the airline booking associated with this transaction."""
    cart_items: NotRequired[Nullable[List[CartItemTypedDict]]]
    r"""An array of cart items that represents the line items of a transaction."""
    statement_descriptor: NotRequired[Nullable[StatementDescriptorTypedDict]]
    r"""Details about the payment and the merchant which may end up on the (bank) statement for the payment."""
    previous_scheme_transaction_id: NotRequired[Nullable[str]]
    r"""A scheme's transaction identifier to use in connecting a merchant initiated transaction to a previous customer initiated transaction. If not provided, and a qualifying customer initiated transaction has been previously made with the stored payment method, then Gr4vy will populate this value with the identifier returned for that transaction. This field is also know as the Visa Transaction Identifier, or Mastercard Trace ID."""
    browser_info: NotRequired[Nullable[BrowserInfoTypedDict]]
    r"""Information about the browser used by the buyer. This can be used by anti-fraud services."""
    shipping_details_id: NotRequired[Nullable[str]]
    r"""The unique identifier of a set of shipping details stored for the buyer. If provided, the created transaction will include a copy of the details at the point of transaction creation; i.e. it will not be affected by later changes to the detail in the database."""
    connection_options: NotRequired[Nullable[Dict[str, Dict[str, Any]]]]
    r"""Allows for passing optional configuration per connection to take advantage of connection specific features. When provided, the data is only passed to the target connection type to prevent sharing configuration across connections. Please note that each of the keys this object are in kebab-case, for example `cybersource-anti-fraud` as they represent the ID of the connector. All the other keys will be snake case, for example `merchant_defined_data` or camel case to match an external API that the connector uses."""
    async_capture: NotRequired[bool]
    r"""Whether to capture the transaction asynchronously.

    - When `async_capture` is `false` (default), the transaction is captured in the same request.
    - When `async_capture` is `true`, the transaction is automatically captured at a later time.

    Redirect transactions are not affected by this flag. This flag can only be set to `true` when `intent` is set to `capture`.
    """
    anti_fraud_fingerprint: NotRequired[Nullable[str]]
    r"""This field represents the fingerprint data to be passed to the active anti-fraud service."""
    payment_service_id: NotRequired[Nullable[str]]
    r"""The unique identifier of an existing payment service. When provided, the created transaction will be processed by the given payment service and any routing rules will be skipped."""
    account_funding_transaction: NotRequired[bool]
    r"""Marks the transaction as an AFT. Requires the payment service to support this feature, and might `recipient` and `buyer` data"""
    allow_partial_authorization: NotRequired[bool]
    r"""Defines if the transaction will allow for a partial authorization."""
    recipient: NotRequired[Nullable[RecipientTypedDict]]
    r"""The recipient of any account to account funding. For use with AFTs."""
    installment_count: NotRequired[Nullable[int]]
    r"""The number of installments a buyer is required to make."""


class TransactionCreate(BaseModel):
    amount: int
    r"""The monetary amount for this transaction, in the smallest currency unit for the given currency, for example `1299` cents to create an authorization for `$12.99`. If the `intent` is set to `capture`, an amount greater than zero must be supplied. All gift card amounts are subtracted from this amount before the remainder is charged to the provided `payment_method`."""

    currency: str
    r"""A supported ISO 4217 currency code. For redirect requests, this value must match the one specified for `currency` in `payment_method`."""

    country: OptionalNullable[str] = UNSET
    r"""The 2-letter ISO code of the country where the transaction is processed. This is also used to filter the payment services that can process the transaction. If this value is provided for redirect requests and it's not `null`, it must match the one specified for `country` in `payment_method`. Otherwise, the value specified for `country` in `payment_method` will be assumed implicitly."""

    payment_method: OptionalNullable[TransactionCreatePaymentMethod] = UNSET
    r"""The optional payment method to use for this transaction. This field is required if no `gift_cards` have been added."""

    buyer: OptionalNullable[GuestBuyerInput] = UNSET
    r"""Guest buyer details provided inline rather than creating a buyer resource beforehand and using the `buyer_id` or `buyer_external_identifier` keys. No buyer resource will be created on Gr4vy when used."""

    buyer_id: OptionalNullable[str] = UNSET
    r"""The ID of the buyer to associate this payment method to. If this field is provided then the `buyer_external_identifier` field needs to be unset. If a stored payment method or gift card is provided, then the buyer for that payment method needs to match the buyer for this field."""

    buyer_external_identifier: OptionalNullable[str] = UNSET
    r"""The `external_identifier` of the buyer to associate this payment method to. If this field is provided then the `buyer_id` field needs to be unset. If a stored payment method or gift card is provided, then the buyer for that payment method needs to match the buyer for this field."""

    gift_cards: OptionalNullable[List[GiftCardUnion]] = UNSET
    r"""The optional gift card(s) to use for this transaction. At least one gift card is required if no other `payment_method` has been added. By default, only a maximum limit of 10 gift cards may be used in a single transaction. Please contact our team to change this limit."""

    external_identifier: OptionalNullable[str] = UNSET
    r"""An external identifier that can be used to match the transaction against your own records."""

    intent: Annotated[
        Optional[TransactionIntent], PlainValidator(validate_open_enum(False))
    ] = None

    store: Optional[bool] = False
    r"""Whether or not to also try and store the payment method with us so that it can be used again for future use. This is only supported for payment methods that support this feature. There are also a few restrictions on how the flag may be set:

    * The flag has to be set to `true` when the `payment_source` is set to `recurring` or `installment`, and `merchant_initiated` is set to `false`.
    * The flag has to be set to `false` (or not set) when using a previously vaulted payment method.
    """

    three_d_secure_data: OptionalNullable[ThreeDSecureData] = UNSET
    r"""Pass through 3-D Secure data to support external 3-D Secure authorisation. If using an external 3-D Secure provider, you should not pass a `redirect_url` in the `payment_method` object for a transaction."""

    metadata: OptionalNullable[Dict[str, str]] = UNSET
    r"""Any additional information about the transaction that you would like to store as key-value pairs. This data is passed to payment service providers that support it."""

    is_subsequent_payment: Optional[bool] = False
    r"""Indicates whether the transaction represents a subsequent payment coming from a setup recurring payment. Please note there are some restrictions on how this flag may be used.

    The flag can only be `false` (or not set) when the transaction meets one of the following criteria:

    * It is not `merchant_initiated`.
    * `payment_source` is set to `card_on_file`.

    The flag can only be set to `true` when the transaction meets one of the following criteria:
    * It is not `merchant_initiated`.
    * `payment_source` is set to `recurring` or `installment` and `merchant_initiated` is set to `true`.
    * `payment_source` is set to `card_on_file`.
    """

    merchant_initiated: Optional[bool] = False
    r"""Indicates whether the transaction was initiated by the merchant (true) or customer (false)."""

    payment_source: Annotated[
        Optional[TransactionPaymentSource], PlainValidator(validate_open_enum(False))
    ] = None
    r"""The way payment method information made it to this transaction."""

    airline: OptionalNullable[Airline] = UNSET
    r"""The airline addendum data which describes the airline booking associated with this transaction."""

    cart_items: OptionalNullable[List[CartItem]] = UNSET
    r"""An array of cart items that represents the line items of a transaction."""

    statement_descriptor: OptionalNullable[StatementDescriptor] = UNSET
    r"""Details about the payment and the merchant which may end up on the (bank) statement for the payment."""

    previous_scheme_transaction_id: OptionalNullable[str] = UNSET
    r"""A scheme's transaction identifier to use in connecting a merchant initiated transaction to a previous customer initiated transaction. If not provided, and a qualifying customer initiated transaction has been previously made with the stored payment method, then Gr4vy will populate this value with the identifier returned for that transaction. This field is also know as the Visa Transaction Identifier, or Mastercard Trace ID."""

    browser_info: OptionalNullable[BrowserInfo] = UNSET
    r"""Information about the browser used by the buyer. This can be used by anti-fraud services."""

    shipping_details_id: OptionalNullable[str] = UNSET
    r"""The unique identifier of a set of shipping details stored for the buyer. If provided, the created transaction will include a copy of the details at the point of transaction creation; i.e. it will not be affected by later changes to the detail in the database."""

    connection_options: OptionalNullable[Dict[str, Dict[str, Any]]] = UNSET
    r"""Allows for passing optional configuration per connection to take advantage of connection specific features. When provided, the data is only passed to the target connection type to prevent sharing configuration across connections. Please note that each of the keys this object are in kebab-case, for example `cybersource-anti-fraud` as they represent the ID of the connector. All the other keys will be snake case, for example `merchant_defined_data` or camel case to match an external API that the connector uses."""

    async_capture: Optional[bool] = False
    r"""Whether to capture the transaction asynchronously.

    - When `async_capture` is `false` (default), the transaction is captured in the same request.
    - When `async_capture` is `true`, the transaction is automatically captured at a later time.

    Redirect transactions are not affected by this flag. This flag can only be set to `true` when `intent` is set to `capture`.
    """

    anti_fraud_fingerprint: OptionalNullable[str] = UNSET
    r"""This field represents the fingerprint data to be passed to the active anti-fraud service."""

    payment_service_id: OptionalNullable[str] = UNSET
    r"""The unique identifier of an existing payment service. When provided, the created transaction will be processed by the given payment service and any routing rules will be skipped."""

    account_funding_transaction: Optional[bool] = False
    r"""Marks the transaction as an AFT. Requires the payment service to support this feature, and might `recipient` and `buyer` data"""

    allow_partial_authorization: Optional[bool] = False
    r"""Defines if the transaction will allow for a partial authorization."""

    recipient: OptionalNullable[Recipient] = UNSET
    r"""The recipient of any account to account funding. For use with AFTs."""

    installment_count: OptionalNullable[int] = UNSET
    r"""The number of installments a buyer is required to make."""

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "country",
            "payment_method",
            "buyer",
            "buyer_id",
            "buyer_external_identifier",
            "gift_cards",
            "external_identifier",
            "intent",
            "store",
            "three_d_secure_data",
            "metadata",
            "is_subsequent_payment",
            "merchant_initiated",
            "payment_source",
            "airline",
            "cart_items",
            "statement_descriptor",
            "previous_scheme_transaction_id",
            "browser_info",
            "shipping_details_id",
            "connection_options",
            "async_capture",
            "anti_fraud_fingerprint",
            "payment_service_id",
            "account_funding_transaction",
            "allow_partial_authorization",
            "recipient",
            "installment_count",
        ]
        nullable_fields = [
            "country",
            "payment_method",
            "buyer",
            "buyer_id",
            "buyer_external_identifier",
            "gift_cards",
            "external_identifier",
            "three_d_secure_data",
            "metadata",
            "airline",
            "cart_items",
            "statement_descriptor",
            "previous_scheme_transaction_id",
            "browser_info",
            "shipping_details_id",
            "connection_options",
            "anti_fraud_fingerprint",
            "payment_service_id",
            "recipient",
            "installment_count",
        ]
        null_default_fields = []

        serialized = handler(self)

        m = {}

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

            optional_nullable = k in optional_fields and k in nullable_fields
            is_set = (
                self.__pydantic_fields_set__.intersection({n})
                or k in null_default_fields
            )  # pylint: disable=no-member

            if val is not None and val != UNSET_SENTINEL:
                m[k] = val
            elif val != UNSET_SENTINEL and (
                not k in optional_fields or (optional_nullable and is_set)
            ):
                m[k] = val

        return m
