# WARNING: This file is autogenerated by FHIR Schema Codegen.
# https://github.com/fhir-schema/fhir-schema-codegen
# Any manual changes made to this file may be overwritten.

from __future__ import annotations
from pydantic import ConfigDict, Field, PositiveInt
from typing import List as PyList, Literal

from fhirschemapy.R4B.base import (
    Annotation,
    BackboneElement,
    CodeableConcept,
    Identifier,
    Money,
    Reference,
)
from fhirschemapy.R4B.domain_resource import DomainResource


class InvoiceLineItem(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    charge_item_codeable_concept: CodeableConcept | None = Field(
        None,
        alias="chargeItemCodeableConcept",
        serialization_alias="chargeItemCodeableConcept",
    )
    charge_item_reference: Reference | None = Field(
        None, alias="chargeItemReference", serialization_alias="chargeItemReference"
    )
    price_component: PyList[InvoiceLineItemPriceComponent] | None = Field(
        None, alias="priceComponent", serialization_alias="priceComponent"
    )
    sequence: PositiveInt | None = Field(
        None, alias="sequence", serialization_alias="sequence"
    )


class InvoiceLineItemPriceComponent(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    amount: Money | None = Field(None, alias="amount", serialization_alias="amount")
    code: CodeableConcept | None = Field(None, alias="code", serialization_alias="code")
    factor: float | None = Field(None, alias="factor", serialization_alias="factor")
    type: Literal[
        "base", "surcharge", "deduction", "discount", "tax", "informational"
    ] = Field(alias="type", serialization_alias="type")


class InvoiceParticipant(BackboneElement):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    actor: Reference = Field(alias="actor", serialization_alias="actor")
    role: CodeableConcept | None = Field(None, alias="role", serialization_alias="role")


class Invoice(DomainResource):
    model_config = ConfigDict(serialize_by_alias=True, extra="forbid")

    resource_type: str = Field(
        default="Invoice",
        alias="resourceType",
        serialization_alias="resourceType",
        frozen=True,
        pattern="Invoice",
    )

    account: Reference | None = Field(
        None, alias="account", serialization_alias="account"
    )
    cancelled_reason: str | None = Field(
        None, alias="cancelledReason", serialization_alias="cancelledReason"
    )
    date: str | None = Field(None, alias="date", serialization_alias="date")
    identifier: PyList[Identifier] | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    issuer: Reference | None = Field(None, alias="issuer", serialization_alias="issuer")
    line_item: PyList[InvoiceLineItem] | None = Field(
        None, alias="lineItem", serialization_alias="lineItem"
    )
    note: PyList[Annotation] | None = Field(
        None, alias="note", serialization_alias="note"
    )
    participant: PyList[InvoiceParticipant] | None = Field(
        None, alias="participant", serialization_alias="participant"
    )
    payment_terms: str | None = Field(
        None, alias="paymentTerms", serialization_alias="paymentTerms"
    )
    recipient: Reference | None = Field(
        None, alias="recipient", serialization_alias="recipient"
    )
    status: Literal["draft", "issued", "balanced", "cancelled", "entered-in-error"] = (
        Field(alias="status", serialization_alias="status")
    )
    subject: Reference | None = Field(
        None, alias="subject", serialization_alias="subject"
    )
    total_gross: Money | None = Field(
        None, alias="totalGross", serialization_alias="totalGross"
    )
    total_net: Money | None = Field(
        None, alias="totalNet", serialization_alias="totalNet"
    )
    total_price_component: PyList[InvoiceLineItemPriceComponent] | None = Field(
        None, alias="totalPriceComponent", serialization_alias="totalPriceComponent"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")

    def to_json(self, indent: int | None = None) -> str:
        return self.model_dump_json(
            exclude_unset=True, exclude_none=True, indent=indent
        )

    @classmethod
    def from_json(cls, json: str) -> Invoice:
        return cls.model_validate_json(json)
