from __future__ import annotations

from datetime import datetime
from enum import StrEnum
from typing import Any, Literal

from pydantic import BaseModel, ConfigDict, Field


class DomainModel(BaseModel):
    model_config = ConfigDict(extra="forbid", str_strip_whitespace=True)


class RdaArtifactType(StrEnum):
    PATIENT = "patient"
    EMERGENCY = "emergency"


class RdaJobState(StrEnum):
    QUEUED = "queued"
    PROCESSING = "processing"
    COMPLETED = "completed"
    FAILED = "failed"


class RdaFieldStatus(StrEnum):
    DOCUMENTAL = "documental"
    INFERIDO = "inferido"
    FALTANTE = "faltante"


class RdaFieldTrace(DomainModel):
    field_path: str
    value: Any = None
    status: RdaFieldStatus
    primary_source: str
    alternate_sources: list[str] = Field(default_factory=list)
    conflict_note: str | None = None


class RdaSectionTrace(RdaFieldTrace):
    """Alias semántico para trazas que se publican como secciones del artefacto."""


class RdaPatientSummary(DomainModel):
    summary_type: Literal["patient"] = "patient"
    patient: dict[str, Any]
    organization: dict[str, Any]
    clinical_background: str | None = None
    diagnoses: list[dict[str, str]] = Field(default_factory=list)


class RdaEmergencySummary(DomainModel):
    summary_type: Literal["emergency"] = "emergency"
    patient: dict[str, Any]
    encounter: dict[str, Any]
    clinical: dict[str, Any]


class RdaArtifact(DomainModel):
    case_key: str
    artifact_type: RdaArtifactType
    version: int | None = None
    schema_version: int
    mapper_version: str
    completeness_status: Literal["complete", "partial"]
    missing_fields: list[str] = Field(default_factory=list)
    section_trace: list[RdaSectionTrace] = Field(default_factory=list)
    payload: dict[str, Any]
    source_context_fingerprint: str | None = None


class RdaGenerationStatus(DomainModel):
    case_key: str
    artifact_type: RdaArtifactType
    status: RdaJobState
    job_id: str | None = None
    error: str | None = None
    source_context_fingerprint: str | None = None
    resolved_version: int | None = None
    reused: bool = False
    updated_at: datetime | None = None
