# This file was auto-generated by Fern from our API Definition.

import datetime as dt
import typing

from ....core.datetime_utils import serialize_datetime
from ...entity_types.types.approval_policy_response import ApprovalPolicyResponse
from ...entity_types.types.entity_id import EntityId
from ...entity_types.types.entity_response import EntityResponse
from ...entity_types.types.entity_user_response import EntityUserResponse
from ...payment_method_types.types.currency_code import CurrencyCode
from ...payment_method_types.types.payment_method_id import PaymentMethodId
from ...payment_method_types.types.payment_method_response import PaymentMethodResponse
from .approval_slot import ApprovalSlot
from .comment_response import CommentResponse
from .invoice_failure_type import InvoiceFailureType
from .invoice_fees_response import InvoiceFeesResponse
from .invoice_id import InvoiceId
from .invoice_line_item_response import InvoiceLineItemResponse
from .invoice_status import InvoiceStatus
from .payment_destination_options import PaymentDestinationOptions
from .payment_source_options import PaymentSourceOptions

try:
    import pydantic.v1 as pydantic  # type: ignore
except ImportError:
    import pydantic  # type: ignore


class InvoiceResponse(pydantic.BaseModel):
    id: InvoiceId
    status: InvoiceStatus
    amount: typing.Optional[float] = pydantic.Field(description="Total amount of invoice in major units")
    currency: typing.Optional[CurrencyCode]
    invoice_date: typing.Optional[dt.datetime] = pydantic.Field(
        alias="invoiceDate", description="Date the invoice was issued."
    )
    deduction_date: typing.Optional[dt.datetime] = pydantic.Field(
        alias="deductionDate", description="Date when funds will be deducted from payer's account."
    )
    settlement_date: typing.Optional[dt.datetime] = pydantic.Field(
        alias="settlementDate", description="Date of funds settlement."
    )
    due_date: typing.Optional[dt.datetime] = pydantic.Field(alias="dueDate", description="Due date of invoice.")
    invoice_number: typing.Optional[str] = pydantic.Field(alias="invoiceNumber")
    note_to_self: typing.Optional[str] = pydantic.Field(alias="noteToSelf")
    service_start_date: typing.Optional[dt.datetime] = pydantic.Field(alias="serviceStartDate")
    service_end_date: typing.Optional[dt.datetime] = pydantic.Field(alias="serviceEndDate")
    payer_id: typing.Optional[EntityId] = pydantic.Field(alias="payerId")
    payer: typing.Optional[EntityResponse]
    payment_source: typing.Optional[PaymentMethodResponse] = pydantic.Field(alias="paymentSource")
    payment_source_id: typing.Optional[PaymentMethodId] = pydantic.Field(alias="paymentSourceId")
    payment_source_options: typing.Optional[PaymentSourceOptions] = pydantic.Field(alias="paymentSourceOptions")
    vendor_id: typing.Optional[EntityId] = pydantic.Field(alias="vendorId")
    vendor: typing.Optional[EntityResponse]
    payment_destination: typing.Optional[PaymentMethodResponse] = pydantic.Field(alias="paymentDestination")
    payment_destination_id: typing.Optional[PaymentMethodId] = pydantic.Field(alias="paymentDestinationId")
    payment_destination_options: typing.Optional[PaymentDestinationOptions] = pydantic.Field(
        alias="paymentDestinationOptions"
    )
    payment_destination_confirmed: bool = pydantic.Field(
        alias="paymentDestinationConfirmed",
        description="True if the payment destination has been confirmed by the vendor. False if the payment destination has been set (for example, a check to an address) but has not been confirmed by the vendor.",
    )
    has_documents: bool = pydantic.Field(
        alias="hasDocuments", description="True if the invoice has documents attached."
    )
    comments: typing.Optional[typing.List[CommentResponse]]
    line_items: typing.Optional[typing.List[InvoiceLineItemResponse]] = pydantic.Field(alias="lineItems")
    approvers: typing.List[ApprovalSlot]
    approval_policy: typing.List[ApprovalPolicyResponse] = pydantic.Field(alias="approvalPolicy")
    metadata: typing.Dict[str, str] = pydantic.Field(description="Metadata associated with this invoice.")
    foreign_id: typing.Optional[str] = pydantic.Field(
        alias="foreignId",
        description="The ID used to identify this invoice in your system. This ID must be unique within each creatorEntity in your system, e.g. two invoices with the same creatorEntity may not have the same foreign ID.",
    )
    creator_user: typing.Optional[EntityUserResponse] = pydantic.Field(
        alias="creatorUser", description="Entity user who created this invoice."
    )
    failure_type: typing.Optional[InvoiceFailureType] = pydantic.Field(
        alias="failureType",
        description="If the invoice failed to be paid, this field will be populated with the type of failure.",
    )
    processed_at: typing.Optional[dt.datetime] = pydantic.Field(alias="processedAt")
    created_at: dt.datetime = pydantic.Field(alias="createdAt")
    updated_at: dt.datetime = pydantic.Field(alias="updatedAt")
    fees: typing.Optional[InvoiceFeesResponse] = pydantic.Field(description="Fees associated with this invoice.")

    def json(self, **kwargs: typing.Any) -> str:
        kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
        return super().json(**kwargs_with_defaults)

    def dict(self, **kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
        kwargs_with_defaults: typing.Any = {"by_alias": True, "exclude_unset": True, **kwargs}
        return super().dict(**kwargs_with_defaults)

    class Config:
        frozen = True
        smart_union = True
        allow_population_by_field_name = True
        json_encoders = {dt.datetime: serialize_datetime}
