from __future__ import annotations

from typing import Any

from app.services.clinical_document_projection import (
    get_structured_document_model,
    render_document_analysis_html,
)
from app.services.clinical_processing import (
    normalizar_lista_medicamentos,
)
from app.services.diagnostic_aids_html_legacy import extract_first_html_paragraph_field
from app.services.factura_html_legacy import (
    extract_factura_procedimientos_from_html,
    is_valid_factura_procedimiento,
)

from .common import (
    _clean_unique_text_list,
    _normalize_whitespace,
)


def normalize_factura_medicamentos(doc: dict[str, Any] | None) -> dict[str, Any] | None:
    if not isinstance(doc, dict):
        return doc
    factura_json = doc.get("factura_json")
    if not isinstance(factura_json, dict):
        return doc
    servicios = factura_json.get("servicios_procedimientos")
    if not isinstance(servicios, dict):
        return doc
    servicios["medicamentos"] = normalizar_lista_medicamentos(servicios.get("medicamentos"), fuente="factura")
    return doc


def _build_factura_procedimiento(
    item: dict[str, Any] | Any, descripcion: Any = None
) -> dict[str, str] | None:
    source = item if isinstance(item, dict) else {"codigo_cups": item, "descripcion": descripcion}
    codigo_normalizado = str(source.get("codigo_cups") or source.get("codigo_referencia") or "").strip()
    descripcion_normalizada = str(source.get("descripcion") or source.get("concepto") or "").strip()
    if not is_valid_factura_procedimiento(codigo_normalizado, descripcion_normalizada):
        return None
    return {
        "codigo_cups": codigo_normalizado,
        "codigo_facturacion": str(source.get("codigo_facturacion") or "").strip(),
        "codigo_referencia": str(source.get("codigo_referencia") or codigo_normalizado).strip(),
        "descripcion": descripcion_normalizada,
    }


def _extraer_procedimientos_factura_json(factura_doc: dict[str, Any]) -> list[dict[str, str]]:
    factura_json = factura_doc.get("factura_json")
    if not isinstance(factura_json, dict):
        return []

    servicios = factura_json.get("servicios_procedimientos") or {}
    procedimientos: list[dict[str, str]] = []
    for item in servicios.get("procedimientos_quirurgicos") or []:
        if not isinstance(item, dict):
            continue
        procedimiento = _build_factura_procedimiento(item)
        if procedimiento:
            procedimientos.append(procedimiento)
    return procedimientos


def _extract_factura_table_html(factura_doc: dict[str, Any]) -> list[dict[str, str]]:
    factura_html = str(factura_doc.get("analisis_html") or render_document_analysis_html(factura_doc) or "")
    if not factura_html:
        return []
    return extract_factura_procedimientos_from_html(factura_html)


def _extraer_procedimientos_factura_html(factura_doc: dict[str, Any]) -> list[dict[str, str]]:
    return _extract_factura_table_html(factura_doc)


def extraer_procedimientos_factura(factura_doc: dict[str, Any] | None) -> list[dict[str, str]]:
    if not isinstance(factura_doc, dict):
        return []

    procedimientos_json = _extraer_procedimientos_factura_json(factura_doc)
    if procedimientos_json:
        return procedimientos_json

    return _extraer_procedimientos_factura_html(factura_doc)


def _imagenologia_factura_display(item: Any) -> str:
    if not isinstance(item, dict):
        return str(item or "").strip()
    estudio = str(item.get("estudio") or item.get("prueba") or item.get("concepto") or "").strip()
    descripcion = str(item.get("descripcion") or "").strip()
    if estudio and descripcion and estudio.lower() != descripcion.lower():
        return f"{estudio} - {descripcion}"
    return estudio or descripcion


def extraer_imagenologia_factura(factura_doc: dict[str, Any] | None) -> list[str]:
    if not isinstance(factura_doc, dict):
        return []
    factura_json = factura_doc.get("factura_json")
    if not isinstance(factura_json, dict):
        return []
    servicios = factura_json.get("servicios_procedimientos") or {}
    return _clean_unique_text_list(
        [_imagenologia_factura_display(item) for item in servicios.get("imagenologia") or []]
    )


def _extract_html_field(html: str, labels: tuple[str, ...]) -> str:
    return extract_first_html_paragraph_field(html, labels)


def _radiologia_interpretacion(doc: dict[str, Any]) -> str:
    structured = get_structured_document_model(doc)
    if structured is not None and hasattr(structured, "conclusion"):
        conclusion = _normalize_whitespace(getattr(structured, "conclusion", "") or "")
        if conclusion and conclusion.lower() not in {"...", "[...]", "no especificado", "no disponible"}:
            return conclusion
    html = str(doc.get("analisis_html") or doc.get("analisis") or render_document_analysis_html(doc) or "")
    conclusion = _extract_html_field(
        html,
        (
            "Conclusión",
            "Conclusion",
            "Conclusión/Impresión diagnóstica",
            "Conclusion/Impresion diagnostica",
            "Impresión diagnóstica",
            "Impresion diagnostica",
        ),
    )
    if conclusion and conclusion.lower() not in {"...", "[...]", "no especificado", "no disponible"}:
        return conclusion
    return "No interpretado"


def _radiologia_display(doc: Any) -> str:
    if not isinstance(doc, dict):
        return str(doc or "").strip()
    structured = get_structured_document_model(doc)
    nombre = ""
    if structured is not None and hasattr(structured, "tipo_estudio"):
        nombre = _normalize_whitespace(getattr(structured, "tipo_estudio", "") or "")
    if not nombre:
        nombre = str(doc.get("nombre_archivo") or doc.get("filename") or doc.get("archivo") or "").strip()
    if not nombre:
        nombre = (
            _extract_html_field(
                str(doc.get("analisis_html") or render_document_analysis_html(doc) or ""),
                ("Tipo de estudio",),
            )
            or "Reporte radiológico"
        )
    return f"{nombre} - {_radiologia_interpretacion(doc)}"


def extraer_imagenes_radiologia(radiologia_docs: Any) -> list[str]:
    if not isinstance(radiologia_docs, list):
        return []
    return _clean_unique_text_list([_radiologia_display(doc) for doc in radiologia_docs])


def extraer_imagenes_diagnosticas(
    factura_doc: dict[str, Any] | None,
    radiologia_docs: Any = None,
) -> list[str]:
    return _clean_unique_text_list(
        [
            *extraer_imagenologia_factura(factura_doc),
            *extraer_imagenes_radiologia(radiologia_docs),
        ]
    )


def _servicios_factura(factura: Any) -> dict[str, Any]:
    if not isinstance(factura, dict):
        return {}
    factura_json = factura.get("factura_json")
    if not isinstance(factura_json, dict):
        return {}
    servicios = factura_json.get("servicios_procedimientos")
    return servicios if isinstance(servicios, dict) else {}
