# 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
from typing import List as PyList, Literal

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


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

    body_site: CodeableConcept | None = Field(
        None, alias="bodySite", serialization_alias="bodySite"
    )
    collected_date_time: str | None = Field(
        None, alias="collectedDateTime", serialization_alias="collectedDateTime"
    )
    collected_period: Period | None = Field(
        None, alias="collectedPeriod", serialization_alias="collectedPeriod"
    )
    collector: Reference | None = Field(
        None, alias="collector", serialization_alias="collector"
    )
    duration: Duration | None = Field(
        None, alias="duration", serialization_alias="duration"
    )
    fasting_status_codeable_concept: CodeableConcept | None = Field(
        None,
        alias="fastingStatusCodeableConcept",
        serialization_alias="fastingStatusCodeableConcept",
    )
    fasting_status_duration: Duration | None = Field(
        None, alias="fastingStatusDuration", serialization_alias="fastingStatusDuration"
    )
    method: CodeableConcept | None = Field(
        None, alias="method", serialization_alias="method"
    )
    quantity: Quantity | None = Field(
        None, alias="quantity", serialization_alias="quantity"
    )


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

    additive_codeable_concept: CodeableConcept | None = Field(
        None,
        alias="additiveCodeableConcept",
        serialization_alias="additiveCodeableConcept",
    )
    additive_reference: Reference | None = Field(
        None, alias="additiveReference", serialization_alias="additiveReference"
    )
    capacity: Quantity | None = Field(
        None, alias="capacity", serialization_alias="capacity"
    )
    description: str | None = Field(
        None, alias="description", serialization_alias="description"
    )
    identifier: PyList[Identifier] | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    specimen_quantity: Quantity | None = Field(
        None, alias="specimenQuantity", serialization_alias="specimenQuantity"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")


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

    additive: PyList[Reference] | None = Field(
        None, alias="additive", serialization_alias="additive"
    )
    description: str | None = Field(
        None, alias="description", serialization_alias="description"
    )
    procedure: CodeableConcept | None = Field(
        None, alias="procedure", serialization_alias="procedure"
    )
    time_date_time: str | None = Field(
        None, alias="timeDateTime", serialization_alias="timeDateTime"
    )
    time_period: Period | None = Field(
        None, alias="timePeriod", serialization_alias="timePeriod"
    )


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

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

    accession_identifier: Identifier | None = Field(
        None, alias="accessionIdentifier", serialization_alias="accessionIdentifier"
    )
    collection: SpecimenCollection | None = Field(
        None, alias="collection", serialization_alias="collection"
    )
    condition: PyList[CodeableConcept] | None = Field(
        None, alias="condition", serialization_alias="condition"
    )
    container: PyList[SpecimenContainer] | None = Field(
        None, alias="container", serialization_alias="container"
    )
    identifier: PyList[Identifier] | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    note: PyList[Annotation] | None = Field(
        None, alias="note", serialization_alias="note"
    )
    parent: PyList[Reference] | None = Field(
        None, alias="parent", serialization_alias="parent"
    )
    processing: PyList[SpecimenProcessing] | None = Field(
        None, alias="processing", serialization_alias="processing"
    )
    received_time: str | None = Field(
        None, alias="receivedTime", serialization_alias="receivedTime"
    )
    request: PyList[Reference] | None = Field(
        None, alias="request", serialization_alias="request"
    )
    status: (
        Literal["available", "unavailable", "unsatisfactory", "entered-in-error"] | None
    ) = Field(None, alias="status", serialization_alias="status")
    subject: Reference | None = Field(
        None, alias="subject", serialization_alias="subject"
    )
    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) -> Specimen:
        return cls.model_validate_json(json)
