from __future__ import annotations

from pathlib import Path
from types import SimpleNamespace

from fastapi.templating import Jinja2Templates

from app.llm.schemas import HistoriaClinicaStructured
from app.services.clinical_processing import (
    extraer_antecedentes_historia,
    extraer_antecedentes_historia_estructurados,
)
from app.services.historia_antecedentes import (
    extract_historia_antecedentes_structured,
    group_antecedentes_for_view,
)


_ROOT = Path(__file__).resolve().parents[1]


HISTORIA_COLUMNAS = """
ANTECEDENTES
DIABETES : NIEGA,                                      OBESIDAD : NIEGA,
HIPERTENSION ARTERIA : NIEGA,                          CARDIOPATÍA : NIEGA,
TABAQUISMO : NIEGA,                                    ASMA : NIEGA,
ALERGICOS : ******** ALERGICO A                        QUIRURGICOS: APENDICECTOMIA, SAFENECTOMIA
LA NITROFURAZONA ********                              DERECHA.
                                                       FARMACOLOGICOS: NIEGA
                                                       TOXICOS: NIEGA
REVISIÓN POR SISTEMAS

ANTECEDENTES PERONSLES
PATOLOGICOS CARDIOPATIA, HPB, INSUFICIENCIA VENOSA
EXAMEN FISICO

ANTECEDENTES
- PATOLOGICOS: NIEGA
- QUIRURGICOS: APENDICECTOMIA, SAFENECTOMIA DERECHA, CIRUGIA OCULAR EN OJO IZQUIERDO
- ALERGICOS: NIEGA
- TOXICOS: NIEGA
EXAMEN FISICO
"""


HISTORIA_TABLA = """
ALERGIA: NIEGA
ALERGIAS
AMOXICILINA: PRURITO, RASH
CEFALEXINA: PRURITO, RASH

ANTECEDENTES
FECHA             TIPO                                DESCRIPCIÓN ANTECEDENTES
09/10/2025        QUIRURGICOS                         REEMPLAZO DE RODILLA IZQUIERDA.
09/10/2025        FARMACOLOGICOS                      TAMSLOSINA TAB 0.4 MG 1 TAB VO DIA.
09/10/2025        PATOLOGICOS                         CARDIOPATIA, HPB, INSUFICIENCIA VENOSA.
09/10/2025        ALERGICOS                           CEFALEXINA
17/01/2025        SISTEMICOS                          SOBREPESO
                                                       EXFUMADOR
25/10/2024        ALERGICOS                           AMOXICILINA
30/05/2023        QUIRURGICOS                         REEMPLAZO TOTAL DE RODILLA IZQUIERDA
24/04/2023        PATOLOGICOS                         NIEGA
24/04/2023        ALERGICOS                           NO CONOCIDOS
EXAMEN FISICO
\f
ANTECEDENTES
PATOLÓGICOS: HIPERTENSION ARTERIAL, DISLIPIDEMIA, HPB, OSTEOARTROSIS
QUIRÚRGICO: REEMPLAZO TOTAL DE RODILLA IZQUIERDA.
FARMACOLÓGICOS: TAMSULOSINA, ENALAPRIL, ATORVASTATINA
ALÉRGICOS: AMOXICILINA - CEFALEXINA
EXAMEN FÍSICO
"""


def _values(items, *, category: str, state: str = "presente") -> list[str]:
    return [
        item.descripcion.casefold() for item in items if item.categoria == category and item.estado == state
    ]


def test_extracts_multicolumn_antecedents_and_groups_negations() -> None:
    items = extract_historia_antecedentes_structured(HISTORIA_COLUMNAS)

    assert _values(items, category="alergico") == ["nitrofurazona"]
    assert set(_values(items, category="quirurgico")) == {
        "apendicectomia",
        "cirugia ocular en ojo izquierdo",
        "safenectomia derecha",
    }
    assert "diabetes" in _values(items, category="patologico", state="negado")
    assert "cardiopatia" in _values(items, category="patologico")
    assert "farmacológicos" in _values(items, category="farmacologico", state="negado")

    allergy = next(item for item in items if item.categoria == "alergico" and item.estado == "presente")
    assert allergy.discordante is True
    view = group_antecedentes_for_view(items)
    assert view["categories"][0]["key"] == "alergico"
    assert view["negative_category_count"] >= 3
    assert view["has_discordance"] is True


def test_extracts_dated_table_across_pages_and_consolidates_duplicates() -> None:
    items = extract_historia_antecedentes_structured(HISTORIA_TABLA)

    allergies = _values(items, category="alergico")
    pathologies = _values(items, category="patologico")
    surgical = _values(items, category="quirurgico")
    systemic = _values(items, category="sistemico")

    assert allergies.count("amoxicilina") == 1
    assert any(value.startswith("cefalexina") for value in allergies)
    assert {"cardiopatia", "hipertension arterial", "dislipidemia", "osteoartrosis"} <= set(pathologies)
    assert len([value for value in surgical if "reemplazo" in value]) == 1
    assert "exfumador" in systemic
    assert any(item.pagina == 2 for item in items if item.descripcion.casefold() == "dislipidemia")
    assert all(item.discordante for item in items if item.categoria == "alergico")


def test_structured_projection_preserves_flat_pdf_contract() -> None:
    model = HistoriaClinicaStructured.model_validate(
        {
            "patient_name": "PACIENTE PRUEBA",
            "resumen_clinico": "Resumen clínico válido para el caso de prueba.",
            "antecedentes_estructurados": [
                {
                    "categoria": "alergico",
                    "descripcion": "Penicilina",
                    "estado": "presente",
                    "evidencia": "ALERGICOS: PENICILINA",
                },
                {
                    "categoria": "patologico",
                    "descripcion": "Diabetes",
                    "estado": "negado",
                },
            ],
        }
    )
    document = {
        "tipo_documento": "historia_clinica",
        "descripcion": "",
        "analysis_structured": model.model_dump(by_alias=True, exclude_none=True),
    }

    structured = extraer_antecedentes_historia_estructurados(document)
    flat = extraer_antecedentes_historia(document)

    assert structured[0]["categoria"] == "alergico"
    assert flat == ["Penicilina"]


def test_epicrisis_panel_uses_compact_cards_and_keeps_pdf_flat_payload() -> None:
    template = (_ROOT / "web" / "epicrisis.html").read_text(encoding="utf-8")
    css = (_ROOT / "static" / "css" / "epicrisis.css").read_text(encoding="utf-8")
    panel = template.split("<!-- Antecedentes -->", maxsplit=1)[1].split(
        "{% if incapacidad_clinica", maxsplit=1
    )[0]

    assert '<ol class="epicrisis-list">' not in panel
    assert 'class="antecedents-grid"' in panel
    assert 'class="antecedents-negatives"' in panel
    assert "Información discordante" in panel
    assert "antecedentesHC:" in template
    assert "grid-template-columns: repeat(auto-fit" in css
    assert "@media (max-width: 720px)" in css


def test_epicrisis_template_renders_structured_antecedents_and_empty_state() -> None:
    template = Jinja2Templates(directory=str(_ROOT / "web")).env.get_template("epicrisis.html")
    view = group_antecedentes_for_view(
        [
            {
                "categoria": "alergico",
                "descripcion": "Nitrofurazona",
                "estado": "presente",
                "discordante": True,
                "evidencia": "ALERGICOS: NITROFURAZONA",
            },
            {
                "categoria": "quirurgico",
                "descripcion": "Apendicectomía",
                "estado": "presente",
            },
            {
                "categoria": "quirurgico",
                "descripcion": "Safenectomía derecha",
                "estado": "presente",
            },
            {
                "categoria": "alergico",
                "descripcion": "Alérgicos",
                "estado": "negado",
                "discordante": True,
            },
        ]
    )

    rendered = template.render(
        nombre_paciente="",
        user=SimpleNamespace(username="tester"),
        metadatos_hc={"caso": "1390913"},
        antecedentes_hc_view=view,
    )
    empty_rendered = template.render(
        nombre_paciente="",
        user=SimpleNamespace(username="tester"),
        metadatos_hc={"caso": "1390913"},
        antecedentes_hc_view=group_antecedentes_for_view([]),
    )

    assert "Nitrofurazona" in rendered
    assert "Apendicectomía" in rendered
    assert "Safenectomía derecha" in rendered
    assert 'aria-label="2 antecedentes">2</span>' in rendered
    assert "Información discordante" in rendered
    assert "Antecedentes negados" in rendered
    assert "ALERGICOS: NITROFURAZONA" in rendered
    assert 'class="epicrisis-panel epicrisis-panel--antecedents"' not in empty_rendered
