from types import SimpleNamespace

from app.config import config
from app.llm.schemas import HistoriaClinicaStructured
from modules.processing.resumen_google import HistoriaClinicaRequest


RAW_HISTORIA = """
Nombre del paciente: JUAN PEREZ
Motivo de consulta: dolor torácico posterior a trauma.
ANTECEDENTES
PATOLÓGICOS: HIPERTENSIÓN ARTERIAL
EXAMEN FÍSICO
Paciente estable, con dolor a la palpación.
"""

CONTAMINATED_NARRATIVE = (
    "Motivo de consulta: dolor torácico posterior a trauma. Examen físico: paciente estable. "
    "Diagnóstico actual: trauma de tórax. Tratamiento: analgesia y observación clínica."
)

RAW_MULTICOLUMN_HISTORIA = """
ANTECEDENTES
EPOC : NIEGA,                        OTROS : PATOLOGICOS: NIEGA
ALERGICOS : ************************* ALERGICO A QUIRURGICOS: APENDICECTOMIA, SAFENECTOMIA
LA NITROFURAZONA ***********         DERECHA.
PRM :
REVISIÓN POR SISTEMAS
\f
ANTECEDENTES
- QUIRURGICOS: APENDICECTOMIA, SAFENECTOMIA DERECHA, CIRUGIA OCULAR EN OJO IZQUIERDO
- ALERGICOS: NIEGA
EXAMEN FISICO
"""


class AntecedentRetryRouter:
    def __init__(self, *, retry_payload=None, fail_retry: bool = False) -> None:
        self.retry_payload = retry_payload
        self.fail_retry = fail_retry
        self.calls = []

    def generate_structured(self, request):
        self.calls.append(request)
        if request.metadata.get("retry_stage") == "antecedents_quality":
            if self.fail_retry:
                raise RuntimeError("retry unavailable")
            payload = self.retry_payload if self.retry_payload is not None else {"ae": []}
        else:
            payload = HistoriaClinicaStructured.model_validate(
                {
                    "pn": "JUAN PEREZ",
                    "rs": (
                        "Paciente consulta por trauma torácico con dolor localizado. "
                        "Se realiza valoración clínica y se define manejo analgésico."
                    ),
                    "an": [CONTAMINATED_NARRATIVE],
                }
            ).model_dump(by_alias=True, exclude_none=True)
        return SimpleNamespace(
            content=payload,
            provider="gemini",
            model=config.GEMINI_MODEL_EXTRACT_HIGH_RISK,
            metrics={},
            output_kind=request.output_kind,
        )


class CanonicalAntecedentRouter:
    def __init__(self) -> None:
        self.calls = []

    def generate_structured(self, request):
        self.calls.append(request)
        payload = HistoriaClinicaStructured.model_validate(
            {
                "rs": "Resumen clínico independiente del proceso de antecedentes.",
                "ae": [
                    {
                        "ct": "alergico",
                        "d": "NITROFURAZONA",
                        "es": "presente",
                        "ev": "ALERGICO A LA NITROFURAZONA",
                        "og": "explicito",
                        "dc": True,
                    },
                    {
                        "ct": "quirurgico",
                        "d": "Apendicectomía",
                        "es": "presente",
                        "ev": "APENDICECTOMIA",
                        "og": "explicito",
                    },
                    {
                        "ct": "quirurgico",
                        "d": "Safenectomía derecha",
                        "es": "presente",
                        "ev": "SAFENECTOMIA DERECHA",
                        "og": "explicito",
                    },
                    {
                        "ct": "quirurgico",
                        "d": "Cirugía ocular en ojo izquierdo",
                        "es": "presente",
                        "ev": "CIRUGIA OCULAR EN OJO IZQUIERDO",
                        "og": "explicito",
                    },
                ],
                "pa": [
                    {"d": "Apendicectomía"},
                    {"d": "Safenectomía derecha"},
                    {"d": "Cirugía ocular en ojo izquierdo"},
                ],
            }
        ).model_dump(by_alias=True, exclude_none=True)
        return SimpleNamespace(
            content=payload,
            provider="gemini",
            model=config.GEMINI_MODEL_EXTRACT_HIGH_RISK,
            metrics={},
            output_kind=request.output_kind,
        )


def test_multicolumn_antecedents_are_complete_without_quality_retry() -> None:
    router = CanonicalAntecedentRouter()

    result = HistoriaClinicaRequest.extraer_historia_estructurada(
        RAW_MULTICOLUMN_HISTORIA,
        llm_router=router,
    )

    assert len(router.calls) == 1
    assert "Versión de prompt: v10" in router.calls[0].prompt
    assert {item.casefold() for item in result.analysis_structured["an"]} == {
        "alergia: nitrofurazona",
        "apendicectomía",
        "safenectomía derecha",
        "cirugía ocular en ojo izquierdo",
    }
    assert all(
        "safenectomia la nitrofurazona" not in item.casefold()
        for item in result.analysis_structured["an"]
    )
    allergy = next(
        item for item in result.analysis_structured["ae"] if item["ct"] == "alergico"
    )
    assert allergy["d"] == "NITROFURAZONA"
    assert "ALERGIA: NITROFURAZONA" in result.analysis_structured["an"]
    assert allergy["dc"] is True
    assert result.quality_metadata["status"] == "ok"
    metrics = result.route_metadata["historia_processing"]["antecedentes"]
    assert metrics["accepted"] == 4
    assert metrics["quality_retries"] == 0
    assert metrics["reason_codes"] == []
    assert metrics["policy_version"] == "v3"


def test_focused_retry_replaces_contaminated_legacy_antecedents() -> None:
    router = AntecedentRetryRouter(
        retry_payload={
            "ae": [
                {
                    "ct": "patologico",
                    "d": "Hipertensión arterial",
                    "es": "presente",
                    "pg": 1,
                    "ev": "PATOLÓGICOS: HIPERTENSIÓN ARTERIAL",
                    "og": "explicito",
                    "cf": "alta",
                }
            ]
        }
    )

    result = HistoriaClinicaRequest.extraer_historia_estructurada(
        RAW_HISTORIA,
        llm_router=router,
    )

    assert len(router.calls) == 2
    assert "Versión de prompt: v10" in router.calls[0].prompt
    assert router.calls[1].metadata["retry_stage"] == "antecedents_quality"
    assert result.analysis_structured["an"] == ["HIPERTENSIÓN ARTERIAL"]
    assert len(result.analysis_structured["ae"]) == 1
    assert result.analysis_structured["ae"][0]["og"] == "explicito"
    assert CONTAMINATED_NARRATIVE not in result.rendered_html
    assert result.quality_metadata["status"] == "ok"
    metrics = result.route_metadata["historia_processing"]["antecedentes"]
    assert metrics["quality_retries"] == 1
    assert metrics["reason_codes"] == []


def test_exhausted_focused_retry_persists_valid_subset_with_degraded_quality() -> None:
    router = AntecedentRetryRouter(fail_retry=True)

    result = HistoriaClinicaRequest.extraer_historia_estructurada(
        RAW_HISTORIA,
        llm_router=router,
    )

    assert result.analysis_structured["an"] == ["HIPERTENSIÓN ARTERIAL"]
    assert CONTAMINATED_NARRATIVE not in result.rendered_html
    assert result.quality_metadata["status"] == "degraded"
    assert "antecedents_retry_exhausted" in result.quality_metadata["reason_codes"]
    assert (
        "antecedents_contaminated_narrative"
        in result.quality_metadata["reason_codes"]
    )
