from __future__ import annotations

from typing import Any

from app.case_epicrisis.domain.models import (
    RecomendacionMedica,
    RecomendacionMedicaCategoria,
)
from app.services.clinical_document_projection import (
    get_structured_document_model,
)
from app.services.clinical_processing import (
    formatear_medicamento_canonico,
    normalizar_lista_medicamentos,
)

from .common import (
    _normalize_whitespace,
)


RECOMMENDATION_CATEGORY_LABELS = {
    RecomendacionMedicaCategoria.INCAPACIDAD.value: "Incapacidad",
    RecomendacionMedicaCategoria.TRATAMIENTO_CUIDADO.value: "Tratamientos y cuidados",
    RecomendacionMedicaCategoria.RESTRICCION.value: "Restricciones",
    RecomendacionMedicaCategoria.SEGUIMIENTO_REHABILITACION.value: "Seguimiento y rehabilitación",
    RecomendacionMedicaCategoria.SIGNO_ALARMA.value: "Signos de alarma",
    RecomendacionMedicaCategoria.OTRA.value: "Otras indicaciones",
}


def build_medication_display_list(items: Any) -> list[str]:
    return [formatear_medicamento_canonico(item) for item in normalizar_lista_medicamentos(items)]


def _format_formulated_medication(item: Any) -> str:
    name = _normalize_whitespace(getattr(item, "nombre", "") or "")
    if not name:
        return ""
    code = _normalize_whitespace(getattr(item, "codigo", "") or "")
    posology = _normalize_whitespace(
        getattr(item, "posologia", "")
        or " ".join(
            str(value).strip()
            for value in (
                getattr(item, "via", ""),
                getattr(item, "frecuencia", ""),
            )
            if str(value or "").strip()
        )
    )
    dose = _normalize_whitespace(getattr(item, "dosis", "") or "")
    quantity = _normalize_whitespace(getattr(item, "cantidad", "") or "")
    description = " - ".join(value for value in (name, posology, dose, quantity) if value)
    return f"{code} - {description}" if code else description


def extract_recomendaciones_medicas(historia: dict[str, Any] | None) -> list[dict[str, Any]]:
    """Proyecta solo recomendaciones ya persistidas en la historia estructurada."""
    if not isinstance(historia, dict):
        return []
    structured = get_structured_document_model(historia)
    if structured is None or not hasattr(structured, "recomendaciones_medicas"):
        return []

    recommendations: list[RecomendacionMedica] = []
    for item in getattr(structured, "recomendaciones_medicas", []) or []:
        recommendations.append(
            RecomendacionMedica(
                categoria=getattr(item, "categoria", RecomendacionMedicaCategoria.OTRA),
                indicacion=getattr(item, "indicacion", "") or "",
                duracion=getattr(item, "periodo_duracion", "") or "",
                fecha=getattr(item, "fecha", "") or "",
                pagina=getattr(item, "pagina", None),
                evidencia=getattr(item, "evidencia", "") or "",
            )
        )

    for medication in getattr(structured, "medicamentos", []) or []:
        if str(getattr(medication, "tipo_uso", "") or "").strip().casefold() != "formulado":
            continue
        indication = _format_formulated_medication(medication)
        if indication:
            recommendations.append(
                RecomendacionMedica(
                    categoria=RecomendacionMedicaCategoria.TRATAMIENTO_CUIDADO,
                    indicacion=indication,
                    duracion=getattr(medication, "duracion", "") or "",
                )
            )

    result: list[dict[str, Any]] = []
    seen: set[tuple[str, str, str]] = set()
    for recommendation in recommendations:
        key = (
            recommendation.categoria.value,
            recommendation.indicacion.casefold(),
            recommendation.duracion.casefold(),
        )
        if key in seen:
            continue
        seen.add(key)
        result.append(recommendation.model_dump(mode="json", exclude_none=True))
    return result


def group_recomendaciones_medicas_for_view(items: Any) -> list[dict[str, Any]]:
    grouped: dict[str, list[dict[str, Any]]] = {category: [] for category in RECOMMENDATION_CATEGORY_LABELS}
    for raw in items if isinstance(items, list) else []:
        if not isinstance(raw, dict):
            continue
        try:
            item = RecomendacionMedica.model_validate(raw)
        except ValueError:
            continue
        if not any((item.indicacion, item.duracion, item.fecha)):
            continue
        grouped[item.categoria.value].append(item.model_dump(mode="json", exclude_none=True))
    return [
        {"key": category, "label": label, "items": grouped[category]}
        for category, label in RECOMMENDATION_CATEGORY_LABELS.items()
        if grouped[category]
    ]
