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

from __future__ import annotations
from .sales_invoice_discount import SalesInvoiceDiscount, SalesInvoiceDiscountTypedDict
from .sales_invoice_email_details import (
    SalesInvoiceEmailDetails,
    SalesInvoiceEmailDetailsTypedDict,
)
from .sales_invoice_line_item import SalesInvoiceLineItem, SalesInvoiceLineItemTypedDict
from .sales_invoice_payment_details import (
    SalesInvoicePaymentDetails,
    SalesInvoicePaymentDetailsTypedDict,
)
from .sales_invoice_payment_term import SalesInvoicePaymentTerm
from .sales_invoice_recipient import (
    SalesInvoiceRecipient,
    SalesInvoiceRecipientTypedDict,
)
from .sales_invoice_status import SalesInvoiceStatus
from mollie.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
from mollie.utils import (
    FieldMetadata,
    HeaderMetadata,
    PathParamMetadata,
    RequestMetadata,
)
import pydantic
from pydantic import model_serializer
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class UpdateSalesInvoiceRequestBodyTypedDict(TypedDict):
    testmode: NotRequired[bool]
    r"""Whether the entity was created in test mode or live mode. This field does not update the mode of the entity.

    Most API credentials are specifically created for either live mode or test mode, in which case this parameter must
    not be sent. For organization-level credentials such as OAuth access tokens, you can enable test mode by setting
    `testmode` to `true`.
    """
    status: NotRequired[SalesInvoiceStatus]
    r"""The status for the invoice to end up in.

    A `draft` invoice is not paid or not sent and can be updated after creation. Setting it to `issued` sends it to
    the recipient so they may then pay through our payment system. To skip our payment process, set this to `paid` to
    mark it as paid. It can then subsequently be sent as well, same as with `issued`.

    A status value that cannot be set but can be returned is `canceled`, for invoices which were
    issued, but then canceled. Currently this can only be done for invoices created in the dashboard.

    Dependent parameters:
    - `paymentDetails` is required if invoice should be set directly to `paid`
    - `customerId` and `mandateId` are required if a recurring payment should be used to set the invoice to `paid`
    - `emailDetails` optional for `issued` and `paid` to send the invoice by email
    """
    memo: NotRequired[Nullable[str]]
    r"""A free-form memo you can set on the invoice, and will be shown on the invoice PDF."""
    payment_term: NotRequired[Nullable[SalesInvoicePaymentTerm]]
    r"""The payment term to be set on the invoice."""
    payment_details: NotRequired[SalesInvoicePaymentDetailsTypedDict]
    email_details: NotRequired[Nullable[SalesInvoiceEmailDetailsTypedDict]]
    recipient_identifier: NotRequired[str]
    r"""An identifier tied to the recipient data. This should be a unique value based on data your system contains,
    so that both you and us know who we're referring to. It is a value you provide to us so that recipient management
    is not required to send a first invoice to a recipient.
    """
    recipient: NotRequired[Nullable[SalesInvoiceRecipientTypedDict]]
    lines: NotRequired[Nullable[List[SalesInvoiceLineItemTypedDict]]]
    r"""Provide the line items for the invoice. Each line contains details such as a description of the item
    ordered and its price.

    All lines must have the same currency as the invoice.
    """
    discount: NotRequired[Nullable[SalesInvoiceDiscountTypedDict]]
    is_e_invoice: NotRequired[bool]
    r"""This indicates whether the invoice is an e-invoice. The default value is `false` and can't be changed
    after the invoice has been issued.

    When `emailDetails` is provided, an additional email is sent to the recipient.
    """


class UpdateSalesInvoiceRequestBody(BaseModel):
    testmode: Optional[bool] = None
    r"""Whether the entity was created in test mode or live mode. This field does not update the mode of the entity.

    Most API credentials are specifically created for either live mode or test mode, in which case this parameter must
    not be sent. For organization-level credentials such as OAuth access tokens, you can enable test mode by setting
    `testmode` to `true`.
    """

    status: Optional[SalesInvoiceStatus] = None
    r"""The status for the invoice to end up in.

    A `draft` invoice is not paid or not sent and can be updated after creation. Setting it to `issued` sends it to
    the recipient so they may then pay through our payment system. To skip our payment process, set this to `paid` to
    mark it as paid. It can then subsequently be sent as well, same as with `issued`.

    A status value that cannot be set but can be returned is `canceled`, for invoices which were
    issued, but then canceled. Currently this can only be done for invoices created in the dashboard.

    Dependent parameters:
    - `paymentDetails` is required if invoice should be set directly to `paid`
    - `customerId` and `mandateId` are required if a recurring payment should be used to set the invoice to `paid`
    - `emailDetails` optional for `issued` and `paid` to send the invoice by email
    """

    memo: OptionalNullable[str] = UNSET
    r"""A free-form memo you can set on the invoice, and will be shown on the invoice PDF."""

    payment_term: Annotated[
        OptionalNullable[SalesInvoicePaymentTerm], pydantic.Field(alias="paymentTerm")
    ] = UNSET
    r"""The payment term to be set on the invoice."""

    payment_details: Annotated[
        Optional[SalesInvoicePaymentDetails], pydantic.Field(alias="paymentDetails")
    ] = None

    email_details: Annotated[
        OptionalNullable[SalesInvoiceEmailDetails], pydantic.Field(alias="emailDetails")
    ] = UNSET

    recipient_identifier: Annotated[
        Optional[str], pydantic.Field(alias="recipientIdentifier")
    ] = None
    r"""An identifier tied to the recipient data. This should be a unique value based on data your system contains,
    so that both you and us know who we're referring to. It is a value you provide to us so that recipient management
    is not required to send a first invoice to a recipient.
    """

    recipient: OptionalNullable[SalesInvoiceRecipient] = UNSET

    lines: OptionalNullable[List[SalesInvoiceLineItem]] = UNSET
    r"""Provide the line items for the invoice. Each line contains details such as a description of the item
    ordered and its price.

    All lines must have the same currency as the invoice.
    """

    discount: OptionalNullable[SalesInvoiceDiscount] = UNSET

    is_e_invoice: Annotated[Optional[bool], pydantic.Field(alias="isEInvoice")] = None
    r"""This indicates whether the invoice is an e-invoice. The default value is `false` and can't be changed
    after the invoice has been issued.

    When `emailDetails` is provided, an additional email is sent to the recipient.
    """

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(
            [
                "testmode",
                "status",
                "memo",
                "paymentTerm",
                "paymentDetails",
                "emailDetails",
                "recipientIdentifier",
                "recipient",
                "lines",
                "discount",
                "isEInvoice",
            ]
        )
        nullable_fields = set(
            ["memo", "paymentTerm", "emailDetails", "recipient", "lines", "discount"]
        )
        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 UpdateSalesInvoiceRequestTypedDict(TypedDict):
    sales_invoice_id: str
    r"""Provide the ID of the related sales invoice."""
    idempotency_key: NotRequired[str]
    r"""A unique key to ensure idempotent requests. This key should be a UUID v4 string."""
    request_body: NotRequired[UpdateSalesInvoiceRequestBodyTypedDict]


class UpdateSalesInvoiceRequest(BaseModel):
    sales_invoice_id: Annotated[
        str,
        pydantic.Field(alias="salesInvoiceId"),
        FieldMetadata(path=PathParamMetadata(style="simple", explode=False)),
    ]
    r"""Provide the ID of the related sales invoice."""

    idempotency_key: Annotated[
        Optional[str],
        pydantic.Field(alias="idempotency-key"),
        FieldMetadata(header=HeaderMetadata(style="simple", explode=False)),
    ] = None
    r"""A unique key to ensure idempotent requests. This key should be a UUID v4 string."""

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

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["idempotency-key", "RequestBody"])
        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


try:
    UpdateSalesInvoiceRequestBody.model_rebuild()
except NameError:
    pass
