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

from __future__ import annotations
from .lineitemtype import LineItemType
from .linkedcustomer import LinkedCustomer, LinkedCustomerTypedDict
from .linkeddepartment import LinkedDepartment, LinkedDepartmentTypedDict
from .linkedinvoiceitem import LinkedInvoiceItem, LinkedInvoiceItemTypedDict
from .linkedledgeraccount import LinkedLedgerAccount, LinkedLedgerAccountTypedDict
from .linkedlocation import LinkedLocation, LinkedLocationTypedDict
from .linkedtaxrate import LinkedTaxRate, LinkedTaxRateTypedDict
from .linkedtrackingcategory import (
    LinkedTrackingCategory,
    LinkedTrackingCategoryTypedDict,
)
from .rebilling import Rebilling, RebillingTypedDict
from apideck_unify import models
from apideck_unify.types import (
    BaseModel,
    Nullable,
    OptionalNullable,
    UNSET,
    UNSET_SENTINEL,
)
from apideck_unify.utils import validate_open_enum
import pydantic
from pydantic import field_serializer, model_serializer
from pydantic.functional_validators import PlainValidator
from typing import List, Optional
from typing_extensions import Annotated, NotRequired, TypedDict


class ExpenseLineItemTypedDict(TypedDict):
    total_amount: Nullable[float]
    r"""The total amount of the expense line item."""
    id: NotRequired[str]
    r"""A unique identifier for an object."""
    tracking_categories: NotRequired[
        Nullable[List[Nullable[LinkedTrackingCategoryTypedDict]]]
    ]
    r"""A list of linked tracking categories."""
    account_id: NotRequired[str]
    r"""The unique identifier for the ledger account. Deprecated, use account instead."""
    account: NotRequired[Nullable[LinkedLedgerAccountTypedDict]]
    customer_id: NotRequired[str]
    r"""The ID of the customer this expense item is linked to. Deprecated in favor of `customer`."""
    customer: NotRequired[Nullable[LinkedCustomerTypedDict]]
    r"""The customer this entity is linked to."""
    department_id: NotRequired[Nullable[str]]
    r"""The ID of the department"""
    department: NotRequired[Nullable[LinkedDepartmentTypedDict]]
    location_id: NotRequired[Nullable[str]]
    r"""The ID of the location"""
    location: NotRequired[Nullable[LinkedLocationTypedDict]]
    tax_rate: NotRequired[LinkedTaxRateTypedDict]
    description: NotRequired[Nullable[str]]
    r"""The expense line item description"""
    type: NotRequired[Nullable[LineItemType]]
    r"""Line Item type"""
    tax_amount: NotRequired[Nullable[float]]
    r"""Tax amount"""
    quantity: NotRequired[Nullable[float]]
    unit_price: NotRequired[Nullable[float]]
    item: NotRequired[LinkedInvoiceItemTypedDict]
    line_number: NotRequired[Nullable[int]]
    r"""Line number of the resource"""
    rebilling: NotRequired[Nullable[RebillingTypedDict]]
    r"""Rebilling metadata for this line item."""


class ExpenseLineItem(BaseModel):
    total_amount: Nullable[float]
    r"""The total amount of the expense line item."""

    id: Optional[str] = None
    r"""A unique identifier for an object."""

    tracking_categories: OptionalNullable[List[Nullable[LinkedTrackingCategory]]] = (
        UNSET
    )
    r"""A list of linked tracking categories."""

    account_id: Annotated[
        Optional[str],
        pydantic.Field(
            deprecated="warning: ** DEPRECATED ** - Deprecated. Use account instead.."
        ),
    ] = None
    r"""The unique identifier for the ledger account. Deprecated, use account instead."""

    account: OptionalNullable[LinkedLedgerAccount] = UNSET

    customer_id: Annotated[
        Optional[str],
        pydantic.Field(
            deprecated="warning: ** DEPRECATED ** - Deprecated. Use customer instead.."
        ),
    ] = None
    r"""The ID of the customer this expense item is linked to. Deprecated in favor of `customer`."""

    customer: OptionalNullable[LinkedCustomer] = UNSET
    r"""The customer this entity is linked to."""

    department_id: OptionalNullable[str] = UNSET
    r"""The ID of the department"""

    department: OptionalNullable[LinkedDepartment] = UNSET

    location_id: OptionalNullable[str] = UNSET
    r"""The ID of the location"""

    location: OptionalNullable[LinkedLocation] = UNSET

    tax_rate: Optional[LinkedTaxRate] = None

    description: OptionalNullable[str] = UNSET
    r"""The expense line item description"""

    type: Annotated[
        OptionalNullable[LineItemType], PlainValidator(validate_open_enum(False))
    ] = UNSET
    r"""Line Item type"""

    tax_amount: OptionalNullable[float] = UNSET
    r"""Tax amount"""

    quantity: OptionalNullable[float] = UNSET

    unit_price: OptionalNullable[float] = UNSET

    item: Optional[LinkedInvoiceItem] = None

    line_number: OptionalNullable[int] = UNSET
    r"""Line number of the resource"""

    rebilling: OptionalNullable[Rebilling] = UNSET
    r"""Rebilling metadata for this line item."""

    @field_serializer("type")
    def serialize_type(self, value):
        if isinstance(value, str):
            try:
                return models.LineItemType(value)
            except ValueError:
                return value
        return value

    @model_serializer(mode="wrap")
    def serialize_model(self, handler):
        optional_fields = [
            "id",
            "tracking_categories",
            "account_id",
            "account",
            "customer_id",
            "customer",
            "department_id",
            "department",
            "location_id",
            "location",
            "tax_rate",
            "description",
            "type",
            "tax_amount",
            "quantity",
            "unit_price",
            "item",
            "line_number",
            "rebilling",
        ]
        nullable_fields = [
            "tracking_categories",
            "account",
            "customer",
            "department_id",
            "department",
            "location_id",
            "location",
            "description",
            "type",
            "total_amount",
            "tax_amount",
            "quantity",
            "unit_price",
            "line_number",
            "rebilling",
        ]
        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
