# 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 (
    BackboneElement,
    CodeableConcept,
    Duration,
    Identifier,
    Quantity,
    Range,
    Reference,
)
from fhirschemapy.R4B.domain_resource import DomainResource


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

    container: SpecimenDefinitionTypeTestedContainer | None = Field(
        None, alias="container", serialization_alias="container"
    )
    handling: PyList[SpecimenDefinitionTypeTestedHandling] | None = Field(
        None, alias="handling", serialization_alias="handling"
    )
    is_derived: bool | None = Field(
        None, alias="isDerived", serialization_alias="isDerived"
    )
    preference: Literal["preferred", "alternate"] = Field(
        alias="preference", serialization_alias="preference"
    )
    rejection_criterion: PyList[CodeableConcept] | None = Field(
        None, alias="rejectionCriterion", serialization_alias="rejectionCriterion"
    )
    requirement: str | None = Field(
        None, alias="requirement", serialization_alias="requirement"
    )
    retention_time: Duration | None = Field(
        None, alias="retentionTime", serialization_alias="retentionTime"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")


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

    additive: PyList[SpecimenDefinitionTypeTestedContainerAdditive] | None = Field(
        None, alias="additive", serialization_alias="additive"
    )
    cap: CodeableConcept | None = Field(None, alias="cap", serialization_alias="cap")
    capacity: Quantity | None = Field(
        None, alias="capacity", serialization_alias="capacity"
    )
    description: str | None = Field(
        None, alias="description", serialization_alias="description"
    )
    material: CodeableConcept | None = Field(
        None, alias="material", serialization_alias="material"
    )
    minimum_volume_quantity: Quantity | None = Field(
        None, alias="minimumVolumeQuantity", serialization_alias="minimumVolumeQuantity"
    )
    minimum_volume_string: str | None = Field(
        None, alias="minimumVolumeString", serialization_alias="minimumVolumeString"
    )
    preparation: str | None = Field(
        None, alias="preparation", serialization_alias="preparation"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")


class SpecimenDefinitionTypeTestedContainerAdditive(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"
    )


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

    instruction: str | None = Field(
        None, alias="instruction", serialization_alias="instruction"
    )
    max_duration: Duration | None = Field(
        None, alias="maxDuration", serialization_alias="maxDuration"
    )
    temperature_qualifier: CodeableConcept | None = Field(
        None, alias="temperatureQualifier", serialization_alias="temperatureQualifier"
    )
    temperature_range: Range | None = Field(
        None, alias="temperatureRange", serialization_alias="temperatureRange"
    )


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

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

    collection: PyList[CodeableConcept] | None = Field(
        None, alias="collection", serialization_alias="collection"
    )
    identifier: Identifier | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    patient_preparation: PyList[CodeableConcept] | None = Field(
        None, alias="patientPreparation", serialization_alias="patientPreparation"
    )
    time_aspect: str | None = Field(
        None, alias="timeAspect", serialization_alias="timeAspect"
    )
    type_collected: CodeableConcept | None = Field(
        None, alias="typeCollected", serialization_alias="typeCollected"
    )
    type_tested: PyList[SpecimenDefinitionTypeTested] | None = Field(
        None, alias="typeTested", serialization_alias="typeTested"
    )

    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) -> SpecimenDefinition:
        return cls.model_validate_json(json)
