"""Constantes y dataclasses del dominio de procesamiento por lotes."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Literal


BATCH_STATUS_RECIBIDO = "recibido"
BATCH_STATUS_PREPARANDO = "preparando"
BATCH_STATUS_PROCESANDO = "procesando"
BATCH_STATUS_ELIMINANDO = "eliminando"
BATCH_STATUS_COMPLETADO = "completado"
BATCH_STATUS_COMPLETADO_CON_ERRORES = "completado_con_errores"
BATCH_STATUS_FALLIDO = "fallido"
BATCH_STATUS_CANCELADO = "cancelado"

INGESTION_MODE_ZIP = "zip"
INGESTION_MODE_MANUAL_HISTORIA = "manual_historia"
INGESTION_MODE_MANUAL_SOPORTE = "manual_soporte"
INGESTION_MODE_PREFACTURA_PDF = "prefactura_pdf"

FILE_STATUS_PENDIENTE = "pendiente"
FILE_STATUS_PROCESANDO = "procesando"
FILE_STATUS_CLASIFICADO = "clasificado"
FILE_STATUS_ASOCIADO = "asociado"
FILE_STATUS_PENDIENTE_VALIDACION = "pendiente_validacion"
FILE_STATUS_FALLIDO = "fallido"

CLINICAL_STATUS_PENDIENTE = "pendiente"
CLINICAL_STATUS_EN_COLA = "en_cola"
CLINICAL_STATUS_PROCESANDO = "procesando"
CLINICAL_STATUS_COMPLETADO = "completado"
CLINICAL_STATUS_FALLIDO = "fallido"

EPICRISIS_STATUS_PENDIENTE = "pendiente"
EPICRISIS_STATUS_EN_COLA = "en_cola"
EPICRISIS_STATUS_PROCESANDO = "procesando"
EPICRISIS_STATUS_COMPLETADO = "completado"
EPICRISIS_STATUS_COMPLETADO_CON_ERRORES = "completado_con_errores"
EPICRISIS_STATUS_FALLIDO = "fallido"

ASSOCIATION_SOURCE_AUTO = "auto"
ASSOCIATION_SOURCE_MANUAL = "manual"

PREFERRED_ASSOCIATION_MODE_VALIDATE_AND_WARN = "validate_and_warn"

TERMINAL_BATCH_STATUSES = {
    BATCH_STATUS_COMPLETADO,
    BATCH_STATUS_COMPLETADO_CON_ERRORES,
    BATCH_STATUS_FALLIDO,
    BATCH_STATUS_CANCELADO,
}

SUPPORTED_DOCUMENT_TYPES = (
    "historia_clinica",
    "prefactura",
    "factura",
    "quirurgico",
    "laboratorio",
    "radiologia",
    "prescripcion",
    "generico",
)


@dataclass
class ExtractedArchiveEntry:
    """Representa un archivo aceptado o rechazado durante la extracción del ZIP."""

    original_name: str
    relative_path: str
    extracted_path: str | None = None
    status: str = FILE_STATUS_PENDIENTE
    error: str = ""


@dataclass
class ArchiveExtractionResult:
    """Agrupa archivos válidos y rechazados después de descomprimir el lote."""

    entries: list[ExtractedArchiveEntry] = field(default_factory=list)
    rejected_entries: list[ExtractedArchiveEntry] = field(default_factory=list)


@dataclass
class ExtractedSignals:
    """Señales normalizadas usadas para clasificar y asociar un documento a un caso."""

    patient_name: str = ""
    patient_id: str = ""
    case_number: str = ""
    service_date: str = ""
    procedure_code: str = ""
    procedure_description: str = ""
    redacted_identity_fields: list[Literal["patient_id", "patient_name"]] = field(default_factory=list)
    evidence: list[str] = field(default_factory=list)


@dataclass
class PrefacturaPdfPage:
    """Texto extraído de una página del PDF compuesto de prefactura."""

    page_number: int
    text: str = ""


@dataclass
class PrefacturaDocumentSegment:
    """Rango de páginas que representa un documento interno del PDF compuesto."""

    document_type: str
    page_start: int
    page_end: int
    page_numbers: list[int] = field(default_factory=list)
    document_title: str = ""
    document_key: str = ""
    document_reference: str = ""
    text: str = ""
    original_name: str = ""


@dataclass
class PrefacturaPageClassification:
    """Clasificación cerrada para una página del PDF compuesto de prefactura."""

    page_number: int
    document_type: str
    document_title: str = ""
    confidence: float = 0.0
    evidence: list[str] = field(default_factory=list)
    reason: str = ""
    source: str = "deterministic"
    is_autonomous: bool = False
    page_text: str = ""


@dataclass
class AssociationDecision:
    """Decisión final de asociación por archivo."""

    file_id: str
    status: str
    case_key: str = ""
    confidence: float = 0.0
    evidence: list[str] = field(default_factory=list)
    patient_name: str = ""
    patient_id: str = ""
    case_number: str = ""
    procedure_code: str = ""
    procedure_description: str = ""
    associated_user: str = ""
    association_source: str = ASSOCIATION_SOURCE_AUTO
    review_required: bool = False
    review_messages: list[str] = field(default_factory=list)
    score_breakdown: dict[str, float] = field(default_factory=dict)
    top_candidates: list[dict[str, Any]] = field(default_factory=list)
    manual_resolution: dict[str, Any] = field(default_factory=dict)


@dataclass
class AssociationResult:
    """Resultado agregado de la asociación automática para todos los archivos del lote."""

    decisions: list[AssociationDecision] = field(default_factory=list)
    cases: list[dict[str, Any]] = field(default_factory=list)
