package com.escolapios.fctmongo.service.processor;

import com.escolapios.fctmongo.dto.GenerarDocumentoContext;
import com.escolapios.fctmongo.entity.Alumno;
import com.escolapios.fctmongo.entity.Convenio;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

@Component
public class Anexo4Processor implements AnexoProcessor {

    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    @Override
    public String getTipoDocumento() {
        return "ANEXO_4"; 
    }


    @Override
    public void procesarDatosEspecificos(GenerarDocumentoContext ctx, Map<String, Object> data) {
        Convenio dto = ctx.datos();
        if (dto == null) return;

        System.out.println("\n🔥 ====== [MOTOR DE TABLAS DINÁMICAS: ANEXO 4] ======");

        // 1. INYECCIÓN DE CABECERAS FIJAS GLOBALES (Fuera de la tabla de alumnos)
        data.put("numeroAcuerdo", desinfectar(dto.getNumeroAcuerdo()));
        data.put("cursoAcademico", desinfectar(dto.getCursoAcademico()));
        data.put("familiaProfesional", desinfectar(dto.getFamiliaProfesionalNombreStr()));  
        data.put("cicloFormativo", dto.getAlumnoCiclo() != null ? dto.getAlumnoCiclo() : "-");
        data.put("nombreEmpresa", desinfectar(dto.getEmpresaNombre()));
        data.put("direccion", desinfectar(dto.getEmpresaDireccion()));

        // Datos del Profesor Tutor del Centro
        data.put("nombreProfesor", desinfectar(dto.getNombreProfesor()));
        data.put("apellidosProfesor", desinfectar(dto.getApellidosProfesor())); 
        data.put("dniProfesor", desinfectar(dto.getDniProfesor()));
        data.put("emailProfesor", desinfectar(dto.getEmailProfesor()));
        // =========================================================================
        // 🟢 EXTRACCIÓN DIRECTA DESDE EL ARRAY NATIVO NOSQL (EVITA GETTERS LOMBOK CORRUPTOS)
        // =========================================================================
        if (dto.getTutoresEmpresa() != null && !dto.getTutoresEmpresa().isEmpty()) {
            
            // Accedemos de forma directa al objeto real de la posición cero del documento NoSQL
            var tutor = dto.getTutoresEmpresa().get(0);
            
            if (tutor != null) {
                // Recuperamos las propiedades crudas resolviendo cualquier conflicto de mapeo de Lombok
                String nombreTut = tutor.getNombre() != null ? tutor.getNombre().trim() : "";
                String apellidosTut = tutor.getApellidos() != null ? tutor.getApellidos().trim() : "";
                String dniTut = tutor.getDni() != null ? tutor.getDni().trim() : "";
                String emailTut = tutor.getEmail() != null ? tutor.getEmail().trim() : "";

                System.out.println("  -> 👔 [DEBUG ANEXO 4] Tutor recuperado con éxito: " + nombreTut + " " + apellidosTut);
                System.out.println("     ├─ DNI extraído de BBDD:   [" + dniTut + "]");
                System.out.println("     ├─ Email extraído de BBDD: [" + emailTut + "]");

                // 1. ⚡ VARIANTES EN CAMELCASE (Para cumplir con tus etiquetas CamelCase)
                data.put("nombreTutorEmpresa", nombreTut);
                data.put("apellidoTutorEmpresa", apellidosTut);
                data.put("dniTutorEmpresa", dniTut);
                data.put("emailTutorEmpresa", emailTut);

                // 3. Alias cortos por compatibilidad de plantillas antiguas
                data.put("nombreTutor", nombreTut);
                data.put("dniTutor", dniTut);
                data.put("emailTutor", emailTut);
            }
        } else {
            System.out.println("  -> ⚠️ [DEBUG ANEXO 4] El array 'tutoresEmpresa' está completamente VACÍO en este convenio.");
            // Inicialización de contingencia defensiva para no dejar llaves crudas
            data.put("dniTutorEmpresa", "");
            data.put("emailTutorEmpresa", "");
            data.put("dnitutorempresa", "");
            data.put("emailtutorempresa", "");
        }

        data.put("fechaHoy", LocalDate.now().format(FORMATTER));
        data.put("fechaFirma", dto.getFechaFirma() != null ? dto.getFechaFirma().format(FORMATTER) : "");

        // 2. ⚡ EXTRACCIÓN DEL DOCUMENTO WORD VIVO DESDE EL MAPA DE CONTINGENCIA
        XWPFDocument doc = (XWPFDocument) data.get("DOCUMENT_RAW_POI"); 
        if (doc == null || doc.getTables().isEmpty()) {
            System.err.println("  -> ❌ ALERTA POI: No se localizó la referencia 'DOCUMENT_RAW_POI' en el mapa de datos.");
            return;
        }

        XWPFTable tablaAlumnos = null;
        int indiceFilaModelo = -1;

        // Escaneamos las tablas del Word buscando la fila molde que contiene tus etiquetas
        for (XWPFTable table : doc.getTables()) {
            for (int r = 0; r < table.getRows().size(); r++) {
                XWPFTableRow fila = table.getRow(r);
                StringBuilder textoFila = new StringBuilder();
                for (XWPFTableCell celda : fila.getTableCells()) {
                    textoFila.append(celda.getText().toUpperCase()).append(" ");
                }
                String textoFilaStr = textoFila.toString();
                
                // Caza semántica: si localiza estas palabras, es la fila repetitiva del Anexo 4
                if (textoFilaStr.contains("NOMBREALUMNO") || textoFilaStr.contains("APELLIDOSALUMNO") || textoFilaStr.contains("DNIALUMNO")) {
                    tablaAlumnos = table;
                    indiceFilaModelo = r;
                    break;
                }
            }
            if (tablaAlumnos != null) break;
        }

        if (tablaAlumnos == null) {
            System.err.println("  -> ❌ ERROR DOCUMENTAL: No se encontró la tabla de alumnos con las llaves {{nombreAlumno}} en tu anexo_4.docx");
            return;
        }

        System.out.println("  🎯 Tabla NoSQL localizada. Fila molde detectada en índice: [" + indiceFilaModelo + "]");

        // 3. CLONACIÓN DINÁMICA FILA POR FILA DE LA RÁFAGA DE ALUMNOS
        List<Alumno> listaAlumnos = dto.getAlumnos();
        if (listaAlumnos != null && !listaAlumnos.isEmpty()) {
            XWPFTableRow filaEstiloModelo = tablaAlumnos.getRow(indiceFilaModelo);
            int totalColumnasModelo = filaEstiloModelo.getTableCells().size();
            
            // Escribiremos inmediatamente debajo de la fila de etiquetas modelo
            int filaDestinoActual = indiceFilaModelo + 1; 
            int numeroSecuencial = 1;

            System.out.println("  -> 👥 Insertando ráfaga masiva tabular de estudiantes. Total a inyectar: " + listaAlumnos.size());

            for (Alumno alu : listaAlumnos) {
                if (alu == null) continue;

                System.out.println("     ├─ Escribiendo Fila [" + filaDestinoActual + "]: " + alu.getNombre() + " " + alu.getApellidos());

                // Creamos la nueva fila heredando de forma segura la altura XML del Word original
                XWPFTableRow filaTrabajo = tablaAlumnos.insertNewTableRow(filaDestinoActual);
                if (filaTrabajo.getCtRow() != null && filaEstiloModelo.getCtRow() != null) {
                    filaTrabajo.getCtRow().setTrPr(filaEstiloModelo.getCtRow().getTrPr());
                }

                // Clonamos e inicializamos cada una de las celdas de la fila molde
                for (int i = 0; i < totalColumnasModelo; i++) {
                    XWPFTableCell celdaModelo = filaEstiloModelo.getCell(i);
                    XWPFTableCell celdaNueva = filaTrabajo.createCell();

                    // Copiamos estilos XML físicos (fondos, bordes de celda)
                    if (celdaModelo != null && celdaModelo.getCTTc() != null && celdaNueva.getCTTc() != null && celdaModelo.getCTTc().getTcPr() != null) {
                        celdaNueva.getCTTc().setTcPr((CTTcPr) celdaModelo.getCTTc().getTcPr().copy());
                    }

                    String textoOriginalEtiqueta = celdaModelo != null ? celdaModelo.getText().trim() : "";

                    // Conservamos intacta la tipografía, tamaño y color corporativo original de tu plantilla
                    String fuente = "Arial"; int tamano = 10; String color = null; boolean esNegrita = false; boolean esCursiva = false;
                    if (celdaModelo != null && !celdaModelo.getParagraphs().isEmpty() && !celdaModelo.getParagraphs().get(0).getRuns().isEmpty()) {
                        XWPFRun runModelo = celdaModelo.getParagraphs().get(0).getRuns().get(0);
                        if (runModelo.getFontFamily() != null) fuente = runModelo.getFontFamily();
                        if (runModelo.getFontSize() != -1) tamano = runModelo.getFontSize();
                        if (runModelo.getColor() != null) color = runModelo.getColor();
                        esNegrita = runModelo.isBold();
                        esCursiva = runModelo.isItalic();
                    }
                    // =========================================================================
                    // 🟢 MAPEO SELECTIVO FILA POR FILA CON LOS DATOS REALES DE ALUMNO.JAVA
                    // =========================================================================
                    String valorFinalInyectar = "";
                    
                    // Si tu primera columna tiene una celda para el número de orden (ej: Nº, 01, 02)
                    if (textoOriginalEtiqueta.equalsIgnoreCase("Nº") || textoOriginalEtiqueta.contains("01") || textoOriginalEtiqueta.equalsIgnoreCase("No")) {
                        valorFinalInyectar = String.format("%02d", numeroSecuencial);
                    } 
                    else if (textoOriginalEtiqueta.contains("{{nombreAlumno}}")) {
                        valorFinalInyectar = alu.getNombre();
                    }
                    else if (textoOriginalEtiqueta.contains("{{apellidosAlumno}}")) {
                        valorFinalInyectar = alu.getApellidos();
                    }
                    else if (textoOriginalEtiqueta.contains("{{dniAlumno}}")) {
                        valorFinalInyectar = alu.getDni();
                    }
                    else if (textoOriginalEtiqueta.contains("{{fechaNacimientoAlumno}}") || textoOriginalEtiqueta.contains("{{echaNacimientoAlumo}}")) {
                        valorFinalInyectar = alu.getFechaNacimiento();
                    }
                    else if (textoOriginalEtiqueta.contains("{{codigoCurso}}")) {
                        valorFinalInyectar = alu.getCodigoCurso();
                    }
                    else if (textoOriginalEtiqueta.contains("{{fechaInicioAlumno}}")) {
                        valorFinalInyectar = alu.getFechaInicio() != null ? alu.getFechaInicio().format(FORMATTER) : "";
                    }
                    else if (textoOriginalEtiqueta.contains("{{fechaFinAlumno}}")) {
                        valorFinalInyectar = alu.getFechaFin() != null ? alu.getFechaFin().format(FORMATTER) : "";
                    }
                    else if (textoOriginalEtiqueta.contains("{{diasSemanaAlumno}}")) {
                        valorFinalInyectar = alu.getDiasSemana();
                    }
                    else if (textoOriginalEtiqueta.contains("{{horaInicioAlumno}}")) {
                        valorFinalInyectar = alu.getHoraInicio();
                    }
                    else if (textoOriginalEtiqueta.contains("{{horaFinAlumno}}")) {
                        valorFinalInyectar = alu.getHoraFin();
                    }
                    else if (textoOriginalEtiqueta.contains("{{horasSemanaAlumno}}")) {
                        valorFinalInyectar = alu.getHorasSemanales() != null ? String.valueOf(alu.getHorasSemanales()) : "0";
                    }
                    else if (textoOriginalEtiqueta.contains("{{totalHorasAlumno}}")) {
                        valorFinalInyectar = alu.getTotalHorasFormacion() != null ? String.valueOf(alu.getTotalHorasFormacion()) : "0";
                    }
                    else {
                        // Conservamos el texto estático de la celda original si no contiene llaves
                        valorFinalInyectar = textoOriginalEtiqueta;
                    }

                    // =========================================================================
                    // 🟢 MANEJO CORRECTO DEL ÁRBOL DE PÁRRAFOS NATIVOS DE APACHE POI
                    // =========================================================================
                    XWPFParagraph parrafo;
                    
                    // Como POI siempre crea un párrafo por defecto al instanciar una celda, lo reutilizamos
                    if (!celdaNueva.getParagraphs().isEmpty()) {
                        parrafo = celdaNueva.getParagraphs().get(0); // 🟢 Tomamos el párrafo base automático
                    } else {
                        parrafo = celdaNueva.addParagraph(); // 🟢 Solo si estuviera vacío (fallback compilable)
                    }
                    
                    // Aplicamos la alineación exacta que tenía la celda molde original
                    if (celdaModelo != null && !celdaModelo.getParagraphs().isEmpty()) {
                        parrafo.setAlignment(celdaModelo.getParagraphs().get(0).getAlignment());
                    }
                    
                    // Limpiamos cualquier "Run" de texto residual que cree POI por defecto
                    while (!parrafo.getRuns().isEmpty()) { 
                        parrafo.removeRun(0); 
                    }
                    
                    // Estampamos el texto final del alumno heredando la tipografía corporativa
                    XWPFRun nuevoRun = parrafo.createRun();
                    nuevoRun.setText(valorFinalInyectar != null ? valorFinalInyectar : "");
                    nuevoRun.setFontFamily(fuente);
                    nuevoRun.setFontSize(tamano);
                    if (color != null) nuevoRun.setColor(color);
                    nuevoRun.setBold(esNegrita);
                    nuevoRun.setItalic(esCursiva);
                    
                    parrafo = celdaNueva.getParagraphs().get(0);
                    if (celdaModelo != null && !celdaModelo.getParagraphs().isEmpty()) {
                        parrafo.setAlignment(celdaModelo.getParagraphs().get(0).getAlignment());
                    }
                    
                    // Limpiamos runs residuales que crea POI por defecto al instanciar celdas
                    while (!parrafo.getRuns().isEmpty()) { 
                        parrafo.removeRun(0); 
                    }
                    
                    // Estampamos el texto formateado final heredando la tipografía corporativa
                    nuevoRun = parrafo.createRun();
                    nuevoRun.setText(valorFinalInyectar != null ? valorFinalInyectar : "");
                    nuevoRun.setFontFamily(fuente);
                    nuevoRun.setFontSize(tamano);
                    if (color != null) nuevoRun.setColor(color);
                    nuevoRun.setBold(esNegrita);
                    nuevoRun.setItalic(esCursiva);
                }
                
                // Avanzamos los contadores secuenciales de la matriz NoSQL
                filaDestinoActual++;
                numeroSecuencial++;
            }

            // 🧼 PURGA DE SEGURIDAD: Eliminamos del Word la fila de etiquetas original (molde) para dejar la tabla limpia
            if (tablaAlumnos.getRows().size() > indiceFilaModelo) {
                tablaAlumnos.removeRow(indiceFilaModelo);
                System.out.println("  -> 🧼 Fila modelo de etiquetas removida del Word final de forma exitosa.");
            }
        } else {
            System.out.println("  -> ⚠️ ALERTA NO-SQL: El array 'alumnos' llegó vacío a este Anexo 4.");
        }
        System.out.println("🔍 =====================================================\n");
    }

    private String desinfectar(String valor) {
        return valor != null ? valor.trim() : "";
    }
}
