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

from __future__ import annotations
from .amount import Amount, AmountTypedDict
from .url import URL, URLTypedDict
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 List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class EntityInvoiceStatus(str, Enum, metaclass=utils.OpenEnumMeta):
    r"""Status of the invoice."""

    OPEN = "open"
    PAID = "paid"
    OVERDUE = "overdue"


class EntityInvoiceNetAmountTypedDict(TypedDict):
    r"""Total amount of the invoice, excluding VAT."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class EntityInvoiceNetAmount(BaseModel):
    r"""Total amount of the invoice, excluding VAT."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class EntityInvoiceVatAmountTypedDict(TypedDict):
    r"""VAT amount of the invoice. Only applicable to merchants registered in the Netherlands. For EU merchants, VAT will
    be shifted to the recipient (as per article 44 and 196 in the EU VAT Directive 2006/112). For merchants outside
    the EU, no VAT will be charged.
    """

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class EntityInvoiceVatAmount(BaseModel):
    r"""VAT amount of the invoice. Only applicable to merchants registered in the Netherlands. For EU merchants, VAT will
    be shifted to the recipient (as per article 44 and 196 in the EU VAT Directive 2006/112). For merchants outside
    the EU, no VAT will be charged.
    """

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class EntityInvoiceGrossAmountTypedDict(TypedDict):
    r"""Total amount of the invoice, including VAT."""

    currency: str
    r"""A three-character ISO 4217 currency code."""
    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class EntityInvoiceGrossAmount(BaseModel):
    r"""Total amount of the invoice, including VAT."""

    currency: str
    r"""A three-character ISO 4217 currency code."""

    value: str
    r"""A string containing an exact monetary amount in the given currency."""


class EntityInvoiceLineTypedDict(TypedDict):
    period: str
    r"""The administrative period in `YYYY-MM` on which the line should be booked."""
    description: str
    r"""Description of the product."""
    count: int
    r"""Number of products invoiced. For example, the number of payments."""
    vat_percentage: int
    r"""VAT percentage rate that applies to this product."""
    amount: AmountTypedDict
    r"""In v2 endpoints, monetary amounts are represented as objects with a `currency` and `value` field."""


class EntityInvoiceLine(BaseModel):
    period: str
    r"""The administrative period in `YYYY-MM` on which the line should be booked."""

    description: str
    r"""Description of the product."""

    count: int
    r"""Number of products invoiced. For example, the number of payments."""

    vat_percentage: Annotated[int, pydantic.Field(alias="vatPercentage")]
    r"""VAT percentage rate that applies to this product."""

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


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

    self_: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    pdf: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""
    documentation: NotRequired[URLTypedDict]
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""


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

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

    pdf: Optional[URL] = None
    r"""In v2 endpoints, URLs are commonly represented as objects with an `href` and `type` field."""

    documentation: Optional[URL] = None
    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(["self", "pdf", "documentation"])
        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 EntityInvoiceTypedDict(TypedDict):
    resource: str
    r"""Indicates that the response contains an invoice object.
    Will always contain the string `invoice` for this endpoint.
    """
    id: str
    reference: str
    r"""The reference number of the invoice. An example value would be: `2024.10000`."""
    vat_number: Nullable[str]
    r"""The VAT number to which the invoice was issued to, if applicable."""
    status: EntityInvoiceStatus
    net_amount: EntityInvoiceNetAmountTypedDict
    r"""Total amount of the invoice, excluding VAT."""
    vat_amount: EntityInvoiceVatAmountTypedDict
    r"""VAT amount of the invoice. Only applicable to merchants registered in the Netherlands. For EU merchants, VAT will
    be shifted to the recipient (as per article 44 and 196 in the EU VAT Directive 2006/112). For merchants outside
    the EU, no VAT will be charged.
    """
    gross_amount: EntityInvoiceGrossAmountTypedDict
    r"""Total amount of the invoice, including VAT."""
    lines: List[EntityInvoiceLineTypedDict]
    r"""The collection of products which make up the invoice."""
    issued_at: str
    r"""The invoice date in `YYYY-MM-DD` format."""
    links: EntityInvoiceLinksTypedDict
    r"""An object with several relevant URLs. Every URL object will contain an `href` and a `type` field."""
    paid_at: NotRequired[Nullable[str]]
    r"""The date on which the invoice was paid, if applicable, in `YYYY-MM-DD` format."""
    due_at: NotRequired[Nullable[str]]
    r"""The date on which the invoice is due, if applicable, in `YYYY-MM-DD` format."""


class EntityInvoice(BaseModel):
    resource: str
    r"""Indicates that the response contains an invoice object.
    Will always contain the string `invoice` for this endpoint.
    """

    id: str

    reference: str
    r"""The reference number of the invoice. An example value would be: `2024.10000`."""

    vat_number: Annotated[Nullable[str], pydantic.Field(alias="vatNumber")]
    r"""The VAT number to which the invoice was issued to, if applicable."""

    status: EntityInvoiceStatus

    net_amount: Annotated[EntityInvoiceNetAmount, pydantic.Field(alias="netAmount")]
    r"""Total amount of the invoice, excluding VAT."""

    vat_amount: Annotated[EntityInvoiceVatAmount, pydantic.Field(alias="vatAmount")]
    r"""VAT amount of the invoice. Only applicable to merchants registered in the Netherlands. For EU merchants, VAT will
    be shifted to the recipient (as per article 44 and 196 in the EU VAT Directive 2006/112). For merchants outside
    the EU, no VAT will be charged.
    """

    gross_amount: Annotated[
        EntityInvoiceGrossAmount, pydantic.Field(alias="grossAmount")
    ]
    r"""Total amount of the invoice, including VAT."""

    lines: List[EntityInvoiceLine]
    r"""The collection of products which make up the invoice."""

    issued_at: Annotated[str, pydantic.Field(alias="issuedAt")]
    r"""The invoice date in `YYYY-MM-DD` format."""

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

    paid_at: Annotated[OptionalNullable[str], pydantic.Field(alias="paidAt")] = UNSET
    r"""The date on which the invoice was paid, if applicable, in `YYYY-MM-DD` format."""

    due_at: Annotated[OptionalNullable[str], pydantic.Field(alias="dueAt")] = UNSET
    r"""The date on which the invoice is due, if applicable, in `YYYY-MM-DD` format."""

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

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = set(["paidAt", "dueAt"])
        nullable_fields = set(["vatNumber", "paidAt", "dueAt"])
        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:
    EntityInvoiceLine.model_rebuild()
except NameError:
    pass
try:
    EntityInvoiceLinks.model_rebuild()
except NameError:
    pass
try:
    EntityInvoice.model_rebuild()
except NameError:
    pass
