# 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

from fhirschemapy.R4B.base import (
    Attachment,
    BackboneElement,
    CodeableConcept,
    Identifier,
    Quantity,
    Range,
    Ratio,
    Reference,
)
from fhirschemapy.R4B.domain_resource import DomainResource


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

    code: CodeableConcept | None = Field(None, alias="code", serialization_alias="code")
    comment: str | None = Field(None, alias="comment", serialization_alias="comment")
    source: PyList[Reference] | None = Field(
        None, alias="source", serialization_alias="source"
    )
    status: CodeableConcept | None = Field(
        None, alias="status", serialization_alias="status"
    )
    status_date: str | None = Field(
        None, alias="statusDate", serialization_alias="statusDate"
    )


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

    amount_quantity: Quantity | None = Field(
        None, alias="amountQuantity", serialization_alias="amountQuantity"
    )
    amount_string: str | None = Field(
        None, alias="amountString", serialization_alias="amountString"
    )
    identifier: Identifier | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    molecular_formula: str | None = Field(
        None, alias="molecularFormula", serialization_alias="molecularFormula"
    )
    name: str | None = Field(None, alias="name", serialization_alias="name")
    optical_activity: CodeableConcept | None = Field(
        None, alias="opticalActivity", serialization_alias="opticalActivity"
    )
    role: CodeableConcept | None = Field(None, alias="role", serialization_alias="role")
    stereochemistry: CodeableConcept | None = Field(
        None, alias="stereochemistry", serialization_alias="stereochemistry"
    )


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

    domain: PyList[CodeableConcept] | None = Field(
        None, alias="domain", serialization_alias="domain"
    )
    jurisdiction: PyList[CodeableConcept] | None = Field(
        None, alias="jurisdiction", serialization_alias="jurisdiction"
    )
    language: PyList[CodeableConcept] | None = Field(
        None, alias="language", serialization_alias="language"
    )
    name: str = Field(alias="name", serialization_alias="name")
    official: PyList[SubstanceSpecificationNameOfficial] | None = Field(
        None, alias="official", serialization_alias="official"
    )
    preferred: bool | None = Field(
        None, alias="preferred", serialization_alias="preferred"
    )
    source: PyList[Reference] | None = Field(
        None, alias="source", serialization_alias="source"
    )
    status: CodeableConcept | None = Field(
        None, alias="status", serialization_alias="status"
    )
    synonym: PyList[SubstanceSpecificationName] | None = Field(
        None, alias="synonym", serialization_alias="synonym"
    )
    translation: PyList[SubstanceSpecificationName] | None = Field(
        None, alias="translation", serialization_alias="translation"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")


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

    authority: CodeableConcept | None = Field(
        None, alias="authority", serialization_alias="authority"
    )
    date: str | None = Field(None, alias="date", serialization_alias="date")
    status: CodeableConcept | None = Field(
        None, alias="status", serialization_alias="status"
    )


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

    amount_quantity: Quantity | None = Field(
        None, alias="amountQuantity", serialization_alias="amountQuantity"
    )
    amount_string: str | None = Field(
        None, alias="amountString", serialization_alias="amountString"
    )
    category: CodeableConcept | None = Field(
        None, alias="category", serialization_alias="category"
    )
    code: CodeableConcept | None = Field(None, alias="code", serialization_alias="code")
    defining_substance_codeable_concept: CodeableConcept | None = Field(
        None,
        alias="definingSubstanceCodeableConcept",
        serialization_alias="definingSubstanceCodeableConcept",
    )
    defining_substance_reference: Reference | None = Field(
        None,
        alias="definingSubstanceReference",
        serialization_alias="definingSubstanceReference",
    )
    parameters: str | None = Field(
        None, alias="parameters", serialization_alias="parameters"
    )


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

    amount_quantity: Quantity | None = Field(
        None, alias="amountQuantity", serialization_alias="amountQuantity"
    )
    amount_range: Range | None = Field(
        None, alias="amountRange", serialization_alias="amountRange"
    )
    amount_ratio: Ratio | None = Field(
        None, alias="amountRatio", serialization_alias="amountRatio"
    )
    amount_ratio_low_limit: Ratio | None = Field(
        None, alias="amountRatioLowLimit", serialization_alias="amountRatioLowLimit"
    )
    amount_string: str | None = Field(
        None, alias="amountString", serialization_alias="amountString"
    )
    amount_type: CodeableConcept | None = Field(
        None, alias="amountType", serialization_alias="amountType"
    )
    is_defining: bool | None = Field(
        None, alias="isDefining", serialization_alias="isDefining"
    )
    relationship: CodeableConcept | None = Field(
        None, alias="relationship", serialization_alias="relationship"
    )
    source: PyList[Reference] | None = Field(
        None, alias="source", serialization_alias="source"
    )
    substance_codeable_concept: CodeableConcept | None = Field(
        None,
        alias="substanceCodeableConcept",
        serialization_alias="substanceCodeableConcept",
    )
    substance_reference: Reference | None = Field(
        None, alias="substanceReference", serialization_alias="substanceReference"
    )


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

    isotope: PyList[SubstanceSpecificationStructureIsotope] | None = Field(
        None, alias="isotope", serialization_alias="isotope"
    )
    molecular_formula: str | None = Field(
        None, alias="molecularFormula", serialization_alias="molecularFormula"
    )
    molecular_formula_by_moiety: str | None = Field(
        None,
        alias="molecularFormulaByMoiety",
        serialization_alias="molecularFormulaByMoiety",
    )
    molecular_weight: SubstanceSpecificationStructureIsotopeMolecularWeight | None = (
        Field(None, alias="molecularWeight", serialization_alias="molecularWeight")
    )
    optical_activity: CodeableConcept | None = Field(
        None, alias="opticalActivity", serialization_alias="opticalActivity"
    )
    representation: PyList[SubstanceSpecificationStructureRepresentation] | None = (
        Field(None, alias="representation", serialization_alias="representation")
    )
    source: PyList[Reference] | None = Field(
        None, alias="source", serialization_alias="source"
    )
    stereochemistry: CodeableConcept | None = Field(
        None, alias="stereochemistry", serialization_alias="stereochemistry"
    )


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

    half_life: Quantity | None = Field(
        None, alias="halfLife", serialization_alias="halfLife"
    )
    identifier: Identifier | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    molecular_weight: SubstanceSpecificationStructureIsotopeMolecularWeight | None = (
        Field(None, alias="molecularWeight", serialization_alias="molecularWeight")
    )
    name: CodeableConcept | None = Field(None, alias="name", serialization_alias="name")
    substitution: CodeableConcept | None = Field(
        None, alias="substitution", serialization_alias="substitution"
    )


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

    amount: Quantity | None = Field(None, alias="amount", serialization_alias="amount")
    method: CodeableConcept | None = Field(
        None, alias="method", serialization_alias="method"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")


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

    attachment: Attachment | None = Field(
        None, alias="attachment", serialization_alias="attachment"
    )
    representation: str | None = Field(
        None, alias="representation", serialization_alias="representation"
    )
    type: CodeableConcept | None = Field(None, alias="type", serialization_alias="type")


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

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

    code: PyList[SubstanceSpecificationCode] | None = Field(
        None, alias="code", serialization_alias="code"
    )
    comment: str | None = Field(None, alias="comment", serialization_alias="comment")
    description: str | None = Field(
        None, alias="description", serialization_alias="description"
    )
    domain: CodeableConcept | None = Field(
        None, alias="domain", serialization_alias="domain"
    )
    identifier: Identifier | None = Field(
        None, alias="identifier", serialization_alias="identifier"
    )
    moiety: PyList[SubstanceSpecificationMoiety] | None = Field(
        None, alias="moiety", serialization_alias="moiety"
    )
    molecular_weight: (
        PyList[SubstanceSpecificationStructureIsotopeMolecularWeight] | None
    ) = Field(None, alias="molecularWeight", serialization_alias="molecularWeight")
    name: PyList[SubstanceSpecificationName] | None = Field(
        None, alias="name", serialization_alias="name"
    )
    nucleic_acid: Reference | None = Field(
        None, alias="nucleicAcid", serialization_alias="nucleicAcid"
    )
    polymer: Reference | None = Field(
        None, alias="polymer", serialization_alias="polymer"
    )
    property: PyList[SubstanceSpecificationProperty] | None = Field(
        None, alias="property", serialization_alias="property"
    )
    protein: Reference | None = Field(
        None, alias="protein", serialization_alias="protein"
    )
    reference_information: Reference | None = Field(
        None, alias="referenceInformation", serialization_alias="referenceInformation"
    )
    relationship: PyList[SubstanceSpecificationRelationship] | None = Field(
        None, alias="relationship", serialization_alias="relationship"
    )
    source: PyList[Reference] | None = Field(
        None, alias="source", serialization_alias="source"
    )
    source_material: Reference | None = Field(
        None, alias="sourceMaterial", serialization_alias="sourceMaterial"
    )
    status: CodeableConcept | None = Field(
        None, alias="status", serialization_alias="status"
    )
    structure: SubstanceSpecificationStructure | None = Field(
        None, alias="structure", serialization_alias="structure"
    )
    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) -> SubstanceSpecification:
        return cls.model_validate_json(json)
