from __future__ import annotations

from typing import Dict, List
import re

from groq import Groq

from app.config import config

from app.services.clinical_processing import extraer_procedimientos_para_soat

def analizar_glosa_y_generar_nota(descripcion_qx: str, hallazgos: str, diagnosticos_html: str, client_groq: Groq) -> str:
    try:
        prompt = f"""
Eres un especialista en auditoría médica y codificación clínica del sistema de salud colombiano. Analiza la coherencia documental para prevenir glosas y propone una Nota Aclaratoria si es necesario.

Diagnósticos/Historia:
{diagnosticos_html}

Descripción Qx / Procedimientos:
{descripcion_qx}

Hallazgos:
{hallazgos}

Formato de respuesta (HTML simple):
<p><b>Análisis de Riesgo de Glosa</b></p>
<ul><li>[puntos clave de riesgo o coherencia]</li></ul>
<p><b>Nota Aclaratoria Recomendada</b></p>
<p>[texto sugerido, si aplica]</p>
"""
        resp = client_groq.chat.completions.create(
            model=config.GROQ_MODEL_CLINICAL,
            temperature=0.0,
            messages=[
                {"role": "system", "content": "Eres auditor clínico. Sé preciso y conciso."},
                {"role": "user", "content": prompt}
            ],
        )
        return resp.choices[0].message.content
    except Exception:
        return ""

def _construir_soat_y_glosa(historia_html: str, qx_html: str, soat_retriever, client_groq: Groq):
    soat_resultados = []
    glosa_html = ""
    if qx_html:
        try:
            procedimientos = extraer_procedimientos_para_soat(qx_html)
            if soat_retriever and procedimientos:
                soat_resultados = soat_retriever.asignar_codigos(procedimientos)
        except Exception:
            soat_resultados = []
    try:
        glosa_html = analizar_glosa_y_generar_nota(
            descripcion_qx=qx_html or "",
            hallazgos=qx_html or "",
            diagnosticos_html=historia_html or "",
            client_groq=client_groq,
        )
    except Exception:
        glosa_html = ""
    return soat_resultados, glosa_html

def _parse_cie10_lines(text: str) -> List[Dict[str, str]]:
    resultados = []
    if not text:
        return resultados
    for line in text.splitlines():
        line = line.strip()
        if not line:
            continue
        m = re.match(r"^Código:\s*(?P<code>[A-Z0-9\.\-]+)\s*-\s*Descripción:\s*(?P<desc>.+)$", line)
        if m:
            resultados.append({"codigo": m.group("code"), "descripcion": m.group("desc")})
        else:
            # fallback: try simple split
            if "-" in line:
                partes = line.split("-", 1)
                resultados.append({"codigo": partes[0].strip(), "descripcion": partes[1].strip()})
    return resultados

def _agente_codificar_desde_soat_item(item: Dict[str, str], soat_retriever, retriever, cups_retriever, client_groq: Groq, client_gemini):
    codigo_soat = (item.get("codigo_soat") or "").strip()
    descripcion = (item.get("descripcion") or "").strip()
    consulta = f"{codigo_soat} {descripcion}".strip()

    # 1. BÚSQUEDA AMPLIADA EN SOAT RAG - Múltiples estrategias
    evidencia_soat = []
    try:
        if soat_retriever and consulta:
            # Búsqueda principal con código y descripción
            docs_principal = soat_retriever.buscar(consulta, k=8)
            
            # Búsqueda adicional solo con código
            docs_codigo = soat_retriever.buscar(codigo_soat, k=6) if codigo_soat else []
            
            # Búsqueda adicional solo con descripción clave
            palabras_clave = " ".join([palabra for palabra in descripcion.split() 
                                     if len(palabra) > 3 and palabra.upper() not in 
                                     ['CON', 'SIN', 'POR', 'DEL', 'LOS', 'LAS', 'UNA', 'DOS', 'TRES']])
            docs_descripcion = soat_retriever.buscar(palabras_clave, k=6) if palabras_clave else []
            
            # Combinar y deduplicar resultados
            todos_docs = docs_principal + docs_codigo + docs_descripcion
            docs_unicos = {}
            for doc in todos_docs:
                key = f"{doc.metadata.get('page', 0)}_{doc.page_content[:100]}"
                if key not in docs_unicos:
                    docs_unicos[key] = doc
            
            evidencia_soat = [
                {
                    "page": d.metadata.get("page"),
                    "extracto": (d.page_content or "")[:1200],
                    "score": getattr(d, 'score', 0.0)
                }
                for d in list(docs_unicos.values())[:12]
            ]
    except Exception as e:
        print(f"Error en búsqueda SOAT: {e}")
        evidencia_soat = []

    # 2. BÚSQUEDA OPTIMIZADA EN CUPS RAG - Por fila completa con contexto
    propuestas_cups = []
    contexto_cups_detallado = ""
    try:
        if descripcion:
            # Búsqueda directa con descripción completa (mantiene contexto semántico)
            df_cups = cups_retriever.asignar_codigos([descripcion])
            
            # Extraer todos los códigos únicos
            for _, row in df_cups.iterrows():
                cups_item = {
                    "procedimiento": row["procedimiento"], 
                    "codigo_cups": row["codigo_cups"],
                    "score": getattr(row, 'score', 0.0)
                }
                # Evitar duplicados por código
                if not any(c["codigo_cups"] == cups_item["codigo_cups"] for c in propuestas_cups):
                    propuestas_cups.append(cups_item)
            
            # Ordenar por relevancia (si hay scores) y limitar
            propuestas_cups = sorted(propuestas_cups, 
                                   key=lambda x: x.get("score", 0.0), 
                                   reverse=True)[:15]
            
            # Crear contexto detallado para el LLM
            contexto_cups_detallado = "\n".join([
                f"CÓDIGO {c['codigo_cups']}: {c['procedimiento']} (Score: {c.get('score', 'N/A')})"
                for c in propuestas_cups
            ])
            
    except Exception as e:
        print(f"Error en búsqueda CUPS: {e}")
        propuestas_cups = []

    # 3. BÚSQUEDA OPTIMIZADA EN CIE-10 RAG - Por fila completa con contexto
    propuestas_cie10 = []
    contexto_cie10_detallado = ""
    try:
        if descripcion:
            # Búsqueda directa con descripción completa (mantiene contexto semántico)
            texto_cie10 = retriever.asignar_codigo_cie10(descripcion)
            propuestas_cie10 = _parse_cie10_lines(texto_cie10)
            
            # Limitar y crear contexto
            propuestas_cie10 = propuestas_cie10[:12]
            contexto_cie10_detallado = "\n".join([
                f"CÓDIGO {c['codigo']}: {c['descripcion']}"
                for c in propuestas_cie10
            ])
            
    except Exception as e:
        print(f"Error en búsqueda CIE-10: {e}")
        propuestas_cie10 = []

    # 4. ANÁLISIS COMPREHENSIVO CON CONTEXTO RAG ENRIQUECIDO
    analisis_completo = ""
    recomendaciones_glosa = ""
    pertinencia_codigos = ""
    
    try:
        # Contexto enriquecido del manual SOAT
        contexto_soat = "\n\n".join([
            f"📄 PÁGINA {e['page']} (Score: {e.get('score', 'N/A')}):\n{e['extracto']}" 
            for e in evidencia_soat[:8]
        ])
        
        prompt = f"""
Eres un especialista en auditoría médica y codificación clínica en Colombia. Analiza el procedimiento SOAT y proporciona un análisis ESTRUCTURADO Y CLARO usando la evidencia RAG.

╔══════════════════════════════════════════════════════════════╗
║ PROCEDIMIENTO SOAT A ANALIZAR                                 ║
╚══════════════════════════════════════════════════════════════╝
• Código SOAT: {codigo_soat}
• Descripción: {descripcion}

╔══════════════════════════════════════════════════════════════╗
║ CONTEXTO RAG DISPONIBLE                                       ║
╚══════════════════════════════════════════════════════════════╝

📚 MANUAL SOAT:
{contexto_soat}

🔧 CÓDIGOS CUPS DISPONIBLES:
{contexto_cups_detallado}

🏥 CÓDIGOS CIE-10 DISPONIBLES:
{contexto_cie10_detallado}

╔══════════════════════════════════════════════════════════════╗
║ FORMATO DE RESPUESTA REQUERIDO                               ║
╚══════════════════════════════════════════════════════════════╝

SECCIÓN 1: VERIFICACIÓN CÓDIGO SOAT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Estado: [CONFIRMADO / NO ENCONTRADO / PARCIAL]
Descripción Oficial: [Del manual SOAT]
Páginas Referencia: [Números de página específicos]
Observaciones: [Notas relevantes del manual]

SECCIÓN 2: CÓDIGOS CUPS RECOMENDADOS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

A) PRINCIPALES (Prioridad Alta):
   • Código: [CUPS] 
     Descripción: [Del RAG]
     Justificación: [Por qué es el más apropiado según RAG]

   • Código: [CUPS]
     Descripción: [Del RAG]
     Justificación: [Por qué complementa el principal]

B) ALTERNATIVOS (Considerar según caso):
   • Código: [CUPS] - [Descripción] - [Cuándo usar]
   • Código: [CUPS] - [Descripción] - [Cuándo usar]

SECCIÓN 3: CÓDIGOS CIE-10 RECOMENDADOS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

A) PRINCIPALES:
   • Código: [CIE-10]
     Descripción: [Del RAG]
     Tipo: [Traumatismo/Osteomuscular/Otro]
     Justificación: [Relación directa con procedimiento]

   • Código: [CIE-10]
     Descripción: [Del RAG]
     Tipo: [Traumatismo/Osteomuscular/Otro]
     Justificación: [Diagnóstico complementario]

B) SECUNDARIOS:
   • Código: [CIE-10] - [Descripción] - [Cuándo incluir]

SECCIÓN 4: ANÁLISIS RIESGO DE GLOSA
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🔴 RIESGOS ALTOS:
   • [Riesgo específico basado en manual SOAT]
   • [Incoherencia identificada]

🟡 RIESGOS MEDIOS:
   • [Documentación parcial]
   • [Ambigüedad en descripción]

🟢 MITIGACIONES:
   • [Acción específica para prevenir glosa]
   • [Documentación adicional sugerida]

SECCIÓN 5: PERTINENCIA Y RECOMENDACIONES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✓ FUNDAMENTO SOAT:
  [Cita específica del manual con páginas]

✓ COHERENCIA CUPS-CIE10:
  [Explicación de por qué esta combinación es óptima]

✓ ACCIONES RECOMENDADAS:
  1. [Acción concreta]
  2. [Documentación requerida]
  3. [Nota aclaratoria sugerida]

IMPORTANTE: 
- USA SOLO los códigos presentes en el contexto RAG
- CITA páginas específicas del manual SOAT
- SÉ ESPECÍFICO y ESTRUCTURADO en cada sección
"""

        if client_gemini and config.LLM_PROVIDER == "gemini":
            response = client_gemini.generate_content(prompt)
            analisis_completo = response.text
        else:
            # Fallback a Groq si Gemini no está disponible
            resp = client_groq.chat.completions.create(
                model=config.GROQ_MODEL_SOAT,
                temperature=0.1,
                messages=[
                    {"role": "system", "content": "Eres un auditor médico experto. Usa TODA la evidencia RAG proporcionada para hacer recomendaciones precisas."},
                    {"role": "user", "content": prompt}
                ],
            )
            analisis_completo = resp.choices[0].message.content
            
        # Extraer secciones específicas del análisis
        if "ANÁLISIS DE RIESGO DE GLOSA:" in analisis_completo:
            glosa_section = analisis_completo.split("ANÁLISIS DE RIESGO DE GLOSA:")[1]
            if "**5." in glosa_section:
                recomendaciones_glosa = glosa_section.split("**5.")[0].strip()
            else:
                recomendaciones_glosa = glosa_section.strip()
        
        if "PERTINENCIA Y JUSTIFICACIÓN:" in analisis_completo:
            pertinencia_codigos = analisis_completo.split("PERTINENCIA Y JUSTIFICACIÓN:")[1].strip()
            
    except Exception as e:
        analisis_completo = f"Error en análisis: {str(e)}"
        recomendaciones_glosa = "No se pudo generar análisis de glosa"
        pertinencia_codigos = "No se pudo generar análisis de pertinencia"

    # 5. NOTA ACLARATORIA ESPECÍFICA
    nota_aclaratoria = ""
    try:
        nota_prompt = f"""
Basándote en el análisis RAG del procedimiento "{descripcion}" y los códigos identificados, redacta una NOTA ACLARATORIA ESPECÍFICA para el posoperatorio inmediato.

Contexto de códigos identificados:
- CUPS principales: {[c['codigo_cups'] for c in propuestas_cups[:3]]}
- CIE-10 principales: {[c['codigo'] for c in propuestas_cie10[:3]]}

La nota debe:
1. Usar terminología médica precisa del contexto RAG
2. Justificar técnicamente el procedimiento realizado
3. Ser concisa pero completa (2-3 líneas)
4. Prevenir glosas específicas identificadas en el análisis

Formato: Nota directa lista para insertar en el expediente.
"""
        if client_gemini and config.LLM_PROVIDER == "gemini":
            resp_nota = client_gemini.generate_content(nota_prompt)
            nota_aclaratoria = resp_nota.text
        else:
            resp_nota = client_groq.chat.completions.create(
                model=config.GROQ_MODEL_SOAT,
                temperature=0.0,
                messages=[
                    {"role": "system", "content": "Redacta notas aclaratorias médicas precisas y técnicas."},
                    {"role": "user", "content": nota_prompt}
                ],
            )
            nota_aclaratoria = resp_nota.choices[0].message.content
    except Exception:
        nota_aclaratoria = "No se pudo generar nota aclaratoria"

    # 6. SELECCIÓN INTELIGENTE BASADA EN RAG
    # Priorizar códigos con mejor contexto y relevancia
    cups_seleccionados = propuestas_cups[:4] if len(propuestas_cups) >= 3 else propuestas_cups[:2]
    cups_alternativas = propuestas_cups[4:10] if len(propuestas_cups) > 4 else propuestas_cups[2:6]
    
    cie10_seleccionados = propuestas_cie10[:5] if len(propuestas_cie10) >= 4 else propuestas_cie10[:3]
    cie10_alternativas = propuestas_cie10[5:12] if len(propuestas_cie10) > 5 else propuestas_cie10[3:8]

    return {
        "input": {"codigo_soat": codigo_soat, "descripcion": descripcion},
        "cups_seleccionados": cups_seleccionados,
        "cups_alternativas": cups_alternativas,
        "cie10_seleccionados": cie10_seleccionados,
        "cie10_alternativas": cie10_alternativas,
        "analisis_completo": analisis_completo,
        "recomendaciones_glosa": recomendaciones_glosa,
        "pertinencia_codigos": pertinencia_codigos,
        "nota_aclaratoria": nota_aclaratoria,
        "evidencia": {
            "soat": evidencia_soat[:8],
            "cups_contexto": contexto_cups_detallado,
            "cie10_contexto": contexto_cie10_detallado
        },
        
        # Mantener compatibilidad con formato anterior
        "justificacion": analisis_completo,
        "cups_seleccionado": cups_seleccionados[0] if cups_seleccionados else None,
        "cie10_seleccionados": cie10_seleccionados if cie10_seleccionados else []
    }

def _extraer_seccion_documento(documento: str, seccion: str) -> str:
    """Extrae una sección específica del documento quirúrgico."""
    try:
        # Normalizar el texto
        texto = documento.upper().replace('\n', ' ').replace('\r', ' ')
        seccion_upper = seccion.upper()
        
        # Buscar la sección
        inicio = texto.find(seccion_upper)
        if inicio == -1:
            return ""
        
        # Encontrar el final de la sección (siguiente sección en mayúsculas o final del documento)
        inicio_contenido = inicio + len(seccion_upper)
        resto_texto = texto[inicio_contenido:]
        
        # Buscar próxima sección
        secciones_posibles = [
            "DIAGNÓSTICOS PREQUIRÚRGICO", "PROCEDIMIENTOS REALIZADOS", 
            "HALLAZGOS QUIRÚRGICOS", "DESCRIPCIÓN DEL PROCEDIMIENTO",
            "JUSTIFICACIÓN DEL PROCEDIMIENTO", "COMPLICACIONES Y SU MANEJO",
            "DIAGNÓSTICOS POSTQUIRÚRGICO"
        ]
        
        fin = len(resto_texto)
        for sec in secciones_posibles:
            if sec != seccion_upper:
                pos = resto_texto.find(sec)
                if pos != -1 and pos < fin:
                    fin = pos
        
        contenido = resto_texto[:fin].strip()
        # Limpiar caracteres extra
        contenido = re.sub(r'\s+', ' ', contenido)
        
        return contenido
        
    except Exception:
        return ""

async def _validar_codigo_soat_con_documento(
    codigo_soat: str,
    descripcion_soat: str,
    diagnosticos_prequx: str,
    procedimientos: str,
    hallazgos: str,
    descripcion_proc: str,
    justificacion: str,
    diagnosticos_postqx: str,
    soat_retriever,
    retriever,
    cups_retriever,
    client_groq: Groq,
    client_gemini
) -> Dict:
    """Valida un código SOAT específico contra la documentación quirúrgica usando Gemini con contexto RAG mejorado."""
    
    # 1. BÚSQUEDA MEJORADA EN MANUAL SOAT
    evidencia_soat = []
    if soat_retriever:
        try:
            # Múltiples estrategias de búsqueda en SOAT
            consultas = [
                f"{codigo_soat} {descripcion_soat}",
                codigo_soat,
                descripcion_soat,
                " ".join([palabra for palabra in descripcion_soat.split() 
                         if len(palabra) > 3 and palabra.upper() not in 
                         ['CON', 'SIN', 'POR', 'DEL', 'LOS', 'LAS', 'UNA', 'DOS', 'TRES']])
            ]
            
            todos_docs_soat = []
            for consulta in consultas:
                if consulta.strip():
                    docs = soat_retriever.buscar(consulta.strip(), k=6)
                    todos_docs_soat.extend(docs)
            
            # Deduplicar y seleccionar mejores resultados
            docs_unicos = {}
            for doc in todos_docs_soat:
                key = f"{doc.metadata.get('page', 0)}_{doc.page_content[:100]}"
                if key not in docs_unicos:
                    docs_unicos[key] = doc
            
            evidencia_soat = [
                {
                    "page": d.metadata.get("page"),
                    "extracto": (d.page_content or "")[:1000],
                }
                for d in list(docs_unicos.values())[:10]
            ]
        except Exception:
            evidencia_soat = []
    
    # 2. BÚSQUEDA OPTIMIZADA DE CIE-10 CON CONTEXTO CLÍNICO - Por fila completa
    propuestas_cie10 = []
    contexto_cie10_completo = ""
    if diagnosticos_prequx or diagnosticos_postqx:
        try:
            # Combinar todos los diagnósticos disponibles en una sola búsqueda contextual
            texto_diagnosticos = f"{diagnosticos_prequx} {diagnosticos_postqx} {hallazgos}".strip()
            
            if texto_diagnosticos:
                # Búsqueda única con contexto completo
                texto_cie10 = retriever.asignar_codigo_cie10(texto_diagnosticos)
                propuestas_cie10 = _parse_cie10_lines(texto_cie10)
                
                # Limitar y crear contexto detallado
                propuestas_cie10 = propuestas_cie10[:15]
                contexto_cie10_completo = "\n".join([
                    f"CIE-10 {c['codigo']}: {c['descripcion']}"
                    for c in propuestas_cie10
                ])
            
        except Exception:
            propuestas_cie10 = []
    
    # 3. BÚSQUEDA OPTIMIZADA DE CUPS CON CONTEXTO QUIRÚRGICO - Por fila completa
    propuestas_cups = []
    contexto_cups_completo = ""
    if procedimientos or descripcion_proc:
        try:
            # Combinar información de procedimientos en una sola búsqueda contextual
            texto_procedimientos = f"{procedimientos} {descripcion_proc}".strip()
            
            if texto_procedimientos:
                # Búsqueda única con contexto completo
                df_cups = cups_retriever.asignar_codigos([texto_procedimientos])
                
                # Extraer todos los códigos únicos
                for _, row in df_cups.iterrows():
                    cups_item = {
                        "procedimiento": row["procedimiento"], 
                        "codigo_cups": row["codigo_cups"]
                    }
                    # Evitar duplicados
                    if not any(c["codigo_cups"] == cups_item["codigo_cups"] for c in propuestas_cups):
                        propuestas_cups.append(cups_item)
                
                propuestas_cups = propuestas_cups[:12]
                contexto_cups_completo = "\n".join([
                    f"CUPS {c['codigo_cups']}: {c['procedimiento']}"
                    for c in propuestas_cups
                ])
            
        except Exception:
            propuestas_cups = []
    
    # 4. ANÁLISIS COMPREHENSIVO CON GEMINI USANDO TODO EL CONTEXTO RAG
    analisis_validacion = ""
    coherencia_documental = ""
    riesgo_glosa = ""
    recomendaciones = ""
    
    try:
        contexto_soat = "\n\n".join([f"📄 Página {e['page']}:\n{e['extracto']}" for e in evidencia_soat[:8]])
        
        prompt = f"""
Eres un auditor médico especialista en facturación SOAT en Colombia. Valida si el código SOAT facturado está justificado usando la evidencia RAG y documentación quirúrgica.

╔══════════════════════════════════════════════════════════════╗
║ CÓDIGO SOAT A VALIDAR                                         ║
╚══════════════════════════════════════════════════════════════╝
• Código: {codigo_soat}
• Descripción Factura: {descripcion_soat}

╔══════════════════════════════════════════════════════════════╗
║ DOCUMENTACIÓN QUIRÚRGICA DISPONIBLE                          ║
╚══════════════════════════════════════════════════════════════╝

📋 DIAGNÓSTICOS PREQUIRÚRGICOS:
{diagnosticos_prequx}

🔧 PROCEDIMIENTOS REALIZADOS:
{procedimientos}

🔍 HALLAZGOS QUIRÚRGICOS:
{hallazgos}

📝 DESCRIPCIÓN DEL PROCEDIMIENTO:
{descripcion_proc}

💡 JUSTIFICACIÓN MÉDICA:
{justificacion}

📊 DIAGNÓSTICOS POSTQUIRÚRGICOS:
{diagnosticos_postqx}

╔══════════════════════════════════════════════════════════════╗
║ CONTEXTO RAG PARA VALIDACIÓN                                 ║
╚══════════════════════════════════════════════════════════════╝

📚 MANUAL SOAT:
{contexto_soat}

🔧 CÓDIGOS CUPS:
{contexto_cups_completo}

🏥 CÓDIGOS CIE-10:
{contexto_cie10_completo}

╔══════════════════════════════════════════════════════════════╗
║ FORMATO DE RESPUESTA REQUERIDO                               ║
╚══════════════════════════════════════════════════════════════╝

SECCIÓN 1: VALIDACIÓN PRINCIPAL
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ESTADO: [✅ JUSTIFICADO / ⚠️ PARCIALMENTE JUSTIFICADO / ❌ NO JUSTIFICADO]

VERIFICACIÓN EN MANUAL SOAT:
• Código existe: [SÍ/NO]
• Descripción coincide: [SÍ/PARCIAL/NO]
• Páginas referencia: [Números específicos]
• Observaciones: [Del manual]

COINCIDENCIA CON DOCUMENTACIÓN:
• Procedimientos documentados respaldan código: [SÍ/PARCIAL/NO]
• Justificación clínica: [SUFICIENTE/INSUFICIENTE]
• Evidencia específica: [Citas de la documentación quirúrgica]

SECCIÓN 2: COHERENCIA DOCUMENTAL
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✓ DIAGNÓSTICOS PRE vs POST:
  [Análisis de coherencia entre diagnósticos]

✓ HALLAZGOS vs PROCEDIMIENTOS:
  [Verificación de que hallazgos justifican procedimientos]

✓ DESCRIPCIÓN vs FACTURA:
  [Coincidencia entre lo descrito y lo facturado]

⚠️ INCONSISTENCIAS IDENTIFICADAS:
  1. [Inconsistencia específica]
  2. [Discrepancia entre documentos]

SECCIÓN 3: CÓDIGOS DE SOPORTE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

A) CIE-10 REQUERIDOS PARA JUSTIFICAR:

PRINCIPAL:
• Código: [CIE-10 del RAG]
  Descripción: [Completa]
  Justificación: [Por qué es necesario para respaldar el SOAT {codigo_soat}]

SECUNDARIOS:
• Código: [CIE-10] - [Descripción] - [Relación con SOAT]
• Código: [CIE-10] - [Descripción] - [Relación con SOAT]

B) CUPS REQUERIDOS PARA JUSTIFICAR:

DIRECTOS:
• Código: [CUPS del RAG]
  Descripción: [Completa]
  Relación: [Correspondencia directa con SOAT {codigo_soat}]

COMPLEMENTARIOS:
• Código: [CUPS] - [Descripción] - [Por qué complementa]

SECCIÓN 4: ANÁLISIS RIESGO DE GLOSA
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🔴 RIESGOS ALTOS (Requieren atención inmediata):
   • [Riesgo específico del manual SOAT]
   • [Documentación faltante crítica]

🟡 RIESGOS MEDIOS (Requieren aclaración):
   • [Ambigüedad en documentación]
   • [Descripción incompleta]

🟢 FORTALEZAS DOCUMENTALES:
   • [Aspectos bien documentados]
   • [Evidencia sólida]

🛡️ MITIGACIONES RECOMENDADAS:
   1. [Acción específica]
   2. [Documentación a agregar]
   3. [Nota aclaratoria]

SECCIÓN 5: RECOMENDACIONES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

📄 DOCUMENTACIÓN ADICIONAL NECESARIA:
   • [Documento específico faltante]
   • [Información a complementar]

📝 NOTA ACLARATORIA SUGERIDA:
   "[Texto específico listo para agregar al expediente, usando terminología del RAG]"

🔧 MEJORAS AL REPORTE QUIRÚRGICO:
   1. [Mejora específica basada en hallazgos vs manual]
   2. [Detalle a agregar]

✅ CONCLUSIÓN VALIDACIÓN:
   [Resumen ejecutivo: código justificado o no, y pasos a seguir]

IMPORTANTE:
- USA SOLO códigos del contexto RAG
- CITA páginas del manual SOAT
- SÉ ESPECÍFICO con ejemplos de la documentación
"""

        if client_gemini and config.LLM_PROVIDER == "gemini":
            response = client_gemini.generate_content(prompt)
            analisis_validacion = response.text
        else:
            # Fallback a Groq si Gemini no está disponible
            resp = client_groq.chat.completions.create(
                model=config.GROQ_MODEL_SOAT,
                temperature=0.1,
                messages=[
                    {"role": "system", "content": "Eres un auditor médico experto en validación SOAT. Usa exclusivamente la evidencia RAG proporcionada."},
                    {"role": "user", "content": prompt}
                ],
            )
            analisis_validacion = resp.choices[0].message.content
            
        # Extraer secciones específicas
        if "COHERENCIA DOCUMENTAL:" in analisis_validacion:
            coherencia_section = analisis_validacion.split("COHERENCIA DOCUMENTAL:")[1]
            if "**3." in coherencia_section:
                coherencia_documental = coherencia_section.split("**3.")[0].strip()
            else:
                coherencia_documental = coherencia_section.strip()
        
        if "ANÁLISIS DE RIESGO DE GLOSA:" in analisis_validacion:
            glosa_section = analisis_validacion.split("ANÁLISIS DE RIESGO DE GLOSA:")[1]
            if "**5." in glosa_section:
                riesgo_glosa = glosa_section.split("**5.")[0].strip()
            else:
                riesgo_glosa = glosa_section.strip()
                
        if "RECOMENDACIONES PARA SUSTENTACIÓN:" in analisis_validacion:
            recomendaciones = analisis_validacion.split("RECOMENDACIONES PARA SUSTENTACIÓN:")[1].strip()
            
    except Exception as e:
        analisis_validacion = f"Error en análisis: {str(e)}"
        coherencia_documental = "No se pudo analizar coherencia"
        riesgo_glosa = "No se pudo evaluar riesgo de glosa"
        recomendaciones = "No se pudieron generar recomendaciones"
    
    return {
        "validacion_resultado": analisis_validacion,
        "coherencia_documental": coherencia_documental,
        "riesgo_glosa": riesgo_glosa,
        "recomendaciones": recomendaciones,
        "cie10_propuestos": propuestas_cie10[:8],
        "cups_propuestos": propuestas_cups[:6],
        "evidencia_soat": evidencia_soat[:8],
        "contexto_rag": {
            "cups_completo": contexto_cups_completo,
            "cie10_completo": contexto_cie10_completo,
            "total_evidencia_soat": len(evidencia_soat)
        }
    }

def _generar_resumen_validacion(resultados: List[Dict], documento_quirurgico: str) -> Dict:
    """Genera un resumen ejecutivo de la validación de toda la factura."""
    total_codigos = len(resultados)
    justificados = sum(1 for r in resultados if "JUSTIFICADO" in r.get("validacion_resultado", ""))
    
    riesgos_altos = []
    recomendaciones_generales = []
    
    for resultado in resultados:
        codigo = resultado.get("codigo_soat", "")
        if "NO JUSTIFICADO" in resultado.get("validacion_resultado", ""):
            riesgos_altos.append(f"Código {codigo}: Falta justificación documental")
        
        if "PARCIALMENTE JUSTIFICADO" in resultado.get("validacion_resultado", ""):
            riesgos_altos.append(f"Código {codigo}: Justificación parcial - requiere documentación adicional")
    
    if not riesgos_altos:
        recomendaciones_generales.append("✅ Todos los códigos están adecuadamente justificados")
    else:
        recomendaciones_generales.append("⚠️ Se identificaron códigos con riesgo de glosa")
        recomendaciones_generales.append("📝 Revisar documentación quirúrgica para códigos señalados")
    
    return {
        "total_codigos_validados": total_codigos,
        "codigos_justificados": justificados,
        "porcentaje_justificacion": round((justificados / total_codigos) * 100, 2) if total_codigos > 0 else 0,
        "riesgos_identificados": riesgos_altos,
        "recomendaciones_generales": recomendaciones_generales,
        "estado_general": "APROBADO" if justificados == total_codigos else "REQUIERE REVISIÓN"
    }

def _parsear_respuesta_gemini_codigos(respuesta: str) -> Dict:
    """
    Parsea la respuesta estructurada de Gemini para extraer códigos CIE-10 y CUPS.
    """
    resultado = {
        "cie10_principal": None,
        "cie10_secundarios": [],
        "cups_principal": None,
        "cups_alternativos": [],
        "analisis_clinico": ""
    }
    
    # Extraer CIE-10 PRINCIPAL
    patron_cie10_principal = r"PRINCIPAL:\s*•\s*Código:\s*([A-Z]\d{1,3}(?:\.\d{1,2})?)\s*Descripción:\s*([^\n]+)\s*Justificación:\s*([^\n]+)"
    match = re.search(patron_cie10_principal, respuesta, re.IGNORECASE | re.DOTALL)
    if match:
        resultado["cie10_principal"] = {
            "codigo": match.group(1).strip(),
            "descripcion": match.group(2).strip(),
            "justificacion": match.group(3).strip()
        }
    
    # Extraer CIE-10 SECUNDARIOS
    seccion_cie10 = re.search(
        r"SECUNDARIOS:(.*?)(?=CÓDIGOS CUPS|$)", 
        respuesta, 
        re.IGNORECASE | re.DOTALL
    )
    if seccion_cie10:
        items = re.findall(
            r"•\s*Código:\s*([A-Z]\d{1,3}(?:\.\d{1,2})?)\s*Descripción:\s*([^\n]+)\s*Justificación:\s*([^\n]+)",
            seccion_cie10.group(1),
            re.IGNORECASE
        )
        for item in items:
            resultado["cie10_secundarios"].append({
                "codigo": item[0].strip(),
                "descripcion": item[1].strip(),
                "justificacion": item[2].strip()
            })
    
    # Extraer CUPS PRINCIPAL
    patron_cups_principal = r"CÓDIGOS CUPS RECOMENDADOS:.*?PRINCIPAL:\s*•\s*Código:\s*(\d{6})\s*Descripción:\s*([^\n]+)\s*Justificación:\s*([^\n]+)"
    match_cups = re.search(patron_cups_principal, respuesta, re.IGNORECASE | re.DOTALL)
    if match_cups:
        resultado["cups_principal"] = {
            "codigo": match_cups.group(1).strip(),
            "descripcion": match_cups.group(2).strip(),
            "justificacion": match_cups.group(3).strip()
        }
    
    # Extraer CUPS ALTERNATIVOS
    seccion_cups = re.search(
        r"ALTERNATIVOS:(.*?)(?=ANÁLISIS CLÍNICO|$)", 
        respuesta, 
        re.IGNORECASE | re.DOTALL
    )
    if seccion_cups:
        items_cups = re.findall(
            r"•\s*Código:\s*(\d{6})\s*Descripción:\s*([^\n]+)\s*Justificación:\s*([^\n]+)",
            seccion_cups.group(1),
            re.IGNORECASE
        )
        for item in items_cups:
            resultado["cups_alternativos"].append({
                "codigo": item[0].strip(),
                "descripcion": item[1].strip(),
                "justificacion": item[2].strip()
            })
    
    # Extraer análisis clínico completo
    analisis_match = re.search(
        r"ANÁLISIS CLÍNICO:(.*?)$",
        respuesta,
        re.IGNORECASE | re.DOTALL
    )
    if analisis_match:
        resultado["analisis_clinico"] = analisis_match.group(1).strip()
    
    return resultado
