package com.escolapios.fctmongo.controller;

import com.escolapios.fctmongo.dto.GenerarDocumentoContext;
import com.escolapios.fctmongo.entity.Alumno;
import com.escolapios.fctmongo.entity.Convenio;
import com.escolapios.fctmongo.entity.Documento;
import com.escolapios.fctmongo.service.ConvenioService;
import com.escolapios.fctmongo.service.DocumentoService;
import com.escolapios.fctmongo.service.EmailService;
import com.escolapios.fctmongo.repository.ConvenioRepository;
import com.escolapios.fctmongo.service.ConvenioMigrationService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/convenios")
@CrossOrigin(origins = "*") // Ajusta esto según tus necesidades de CORS
public class ConvenioController {
    private final ConvenioService convenioService;
    private final ConvenioRepository convenioRepository;
    @Autowired
    private final ConvenioMigrationService convenioMigrationService;
    @Autowired
    private EmailService emailService;
    @Autowired
    private DocumentoService documentoService;
    public ConvenioController(ConvenioService convenioService,
                                ConvenioMigrationService convenioMigrationService,
                                ConvenioRepository convenioRepository,
                                EmailService emailService,
                                DocumentoService documentoService) {
        this.convenioService = convenioService;
        this.convenioMigrationService = convenioMigrationService;
        this.convenioRepository = convenioRepository;
        this.emailService = emailService;
        this.documentoService = documentoService;
    }
    // 1. ENDPOINT FIJO (Debe ir ARRIBA para que no se confunda con un ID)

    @GetMapping("/siguiente-numero-acuerdo")
    public ResponseEntity<String> obtenerSiguienteNumeroAcuerdo() {
        try {
            List<Convenio> convenios = convenioRepository.findAllNumeroAcuerdoOnly();
            int maxSecuencial = 0;
            for (Convenio c : convenios) {
                if (c.getNumeroAcuerdo() != null) {
                    try {
                        String codigo = c.getNumeroAcuerdo().trim();
                        String[] partes = codigo.split("-");
                        if (partes.length > 0) {
                            int numeroVal = Integer.parseInt(partes[0].trim());
                            if (numeroVal > maxSecuencial) {
                                maxSecuencial = numeroVal;
                            }
                        }
                    } catch (Exception e) {
                        // Ignorar formatos corruptos
                    }
                }
            }
            return ResponseEntity.ok((maxSecuencial + 1) + "-CM");
        } catch (Exception e) {
            return new ResponseEntity<>("1-CM", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/listar")
    public ResponseEntity<Page<Convenio>> listarConvenios(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(required = false) String texto) {      
        
        Pageable pageable = org.springframework.data.domain.PageRequest.of(page, 10);
        Page<Convenio> paginaConvenios;
        
        // 🟢 Si el usuario ha escrito un criterio en el buscador del frontal
        if (texto != null && !texto.trim().isEmpty()) {
            String filtro = texto.trim();
            
            // 1. Intentamos buscar por Número de Acuerdo (ej: "12-CM")
            paginaConvenios = convenioRepository.findByNumeroAcuerdoContainingIgnoreCase(filtro, pageable);
            
            // 2. Si no encuentra nada, intentamos por el Nombre de la Empresa Snapshot
            if (paginaConvenios.isEmpty()) {
                paginaConvenios = convenioRepository.findByEmpresaNombreContainingIgnoreCase(filtro, pageable);
            }
            
            // 3. Si sigue vacío, intentamos por el Curso Académico (ej: "2025/2026")
            if (paginaConvenios.isEmpty()) {
                paginaConvenios = convenioRepository.findByCursoAcademicoContainingIgnoreCase(filtro, pageable);
            }
        } else {
            // Listado normal por defecto de siempre
            paginaConvenios = convenioRepository.findAll(pageable);
        }
        
        return ResponseEntity.ok(paginaConvenios);
    }


    // 3. ENDPOINT DINÁMICO (Siempre ABAJO de las rutas fijas)
    @GetMapping("/{id}")
    public ResponseEntity<Convenio> obtenerPorId(@PathVariable String id) {
        return convenioRepository.findById(id)
                .map(ResponseEntity::ok)
                .orElseGet(() -> ResponseEntity.notFound().build());
    }

    @PostMapping
    public ResponseEntity<?> crearConvenio(@RequestBody Convenio convenio) {
        try {
            // 1. Validación NoSQL anti-duplicados previa...
            if (convenio.getNumeroAcuerdo() != null) {
                String numeroLimpio = convenio.getNumeroAcuerdo().trim();
                if (convenioRepository.existsByNumeroAcuerdo(numeroLimpio)) {
                    return ResponseEntity.status(HttpStatus.CONFLICT).body("El número de acuerdo ya existe.");
                }
            }

            // 2. Insertamos el convenio en estado de revisión intermedio
            convenio.setEstado("PENDIENTE_APROBACION");
            convenio.setId(null); 
            Convenio convenioGuardado = convenioRepository.save(convenio);

            // 3. 🟢 DISPARO AUTOMÁTICO DEL CIRCUITO DE CORREO
            try {
                // Pasamos el ID del convenio recién guardado para que viaje al DTO y al Record
                byte[] pdfBytes = documentoService.obtenerBytesBorradorConvenio(convenioGuardado.getId());
                
                if (pdfBytes != null) {
                    String empresaNombre = convenioGuardado.getEmpresa() != null 
                            ? convenioGuardado.getEmpresa().getNombre() 
                            : "Sin Empresa";
                    // 🟢 Añadimos un String vacío como cuarto parámetro para que compile correctamente
                    emailService.enviarSolicitudAprobacion(convenioGuardado.getNumeroAcuerdo(), 
                                            empresaNombre, 
                                            pdfBytes, 
                                            "",
                                        "convenio");
                }
            } catch (Exception ex) {
                System.err.println("⚠️ Convenio guardado pero falló la cola de email: " + ex.getMessage());
            }

            return new ResponseEntity<>(convenioGuardado, HttpStatus.CREATED);

        } catch (Exception e) {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

        /**
     * 🔄 ACTUALIZACIÓN DIRECTA (El Front envía el documento entero)
     * PUT -> http://localhost:8080/api/convenios/{id}
     */
    @PutMapping("/{id}")
    public ResponseEntity<Convenio> actualizarConvenio(@PathVariable String id, @RequestBody Convenio convenio) {
        // Forzamos el ID de la URL al objeto para asegurar que sobreescriba el registro correcto
        convenio.setId(id); 
        
        // Guardamos el convenio completo en MongoDB tal y como vino del frontal
        Convenio actualizado = convenioService.guardar(convenio);
        
        // ⚡ CLAVE LOMBOK: Forzamos el aplanamiento de variables planos antes de responder al Frontend
        // Esto garantiza que el JSON de respuesta contenga 'cicloAlumno', 'empresaNombre', etc.
        actualizado.sincronizarCamposPlanosTemplate();
        
        return ResponseEntity.ok(actualizado);
    }

    @GetMapping
    public ResponseEntity<List<Convenio>> obtenerTodos() {
        return ResponseEntity.ok(convenioService.obtenerTodos());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> eliminarConvenio(@PathVariable String id) {
        convenioService.eliminar(id);
        return ResponseEntity.noContent().build();
    }
    /**
     * 📋 LISTAR TODOS CON DETALLES
     * GET -> http://localhost:8080/api/convenios/detalles-completos
     */
    @GetMapping("/detalles-completos")
    public ResponseEntity<List<Convenio>> listarConDetalles() {
        // Invocamos al servicio simplificado que devuelve las entidades completas de MongoDB
        List<Convenio> listaConvenios = convenioService.obtenerConveniosConDetalles();
        return ResponseEntity.ok(listaConvenios);
    }

    /**
     * 🔍 OBTENER CONVENIO PADRE DE UN ALUMNO
     * GET -> http://localhost:8080/api/convenios/alumno/{alumnoId}
     */
    @GetMapping("/alumno/{alumnoId}")
    public ResponseEntity<Convenio> obtenerConvenioPadreDeAlumno(@PathVariable String alumnoId) {
        System.out.println("🔍 [ConvenioController] Localizando acuerdo directo para el Alumno ID: " + alumnoId);       
        
        // Buscamos la entidad Convenio unificada en lugar del DTO obsoleto
        Convenio convenio = convenioService.obtenerConvenioPorAlumnoEmbebido(alumnoId);
        if (convenio == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(convenio);
    }

    // GET /api/alumnos
    @GetMapping("/alumnos")
    public ResponseEntity listarTodosLosAlumnosEmbebidos() {
        System.out.println("🔍 [ConvenioController] Extrayendo ráfaga global de alumnos desde los convenios NoSQL...");    
        List listaGlobalAlumnos = convenioService.extraerAlumnosDeTodosLosConvenios();
        System.out.println("-> Total alumnos localizados en la base de datos: " + listaGlobalAlumnos.size());
        return ResponseEntity.ok(listaGlobalAlumnos);
    }

    /**
     * 🟢 ENLACE DE VALIDACIÓN POR NÚMERO DE ACUERDO (Para el correo del Jefe de Estudios)
     * GET -> http://localhost:8080/api/convenios/validar/acuerdo/{numeroAcuerdo}
     */
    @GetMapping("/validar/{numeroAcuerdo}")
    @ResponseBody
    public String validarConvenioPorNumeroAcuerdo(@PathVariable String numeroAcuerdo) {
        try {
            // 1. Buscamos el convenio en MongoDB utilizando su código String (ej: "12-CM")
            Optional<Convenio> convenioOpt = convenioRepository.findByNumeroAcuerdo(numeroAcuerdo.trim());
            
            if (convenioOpt.isPresent()) {
                Convenio convenio = convenioOpt.get();
                
                // 2. Control anti dobles clics
                if ("APROBADO".equals(convenio.getEstado())) {
                    return "<div style='text-align:center; margin-top:50px; font-family:sans-serif;'>"
                            + "<h2>📋 Aviso del Sistema</h2>"
                            + "<p>El convenio con Nº Acuerdo " + numeroAcuerdo + " ya había sido aprobado previamente.</p>"
                            + "</div>";
                }

                // 3. Cambiamos el estado a APROBADO y guardamos en NoSQL
                convenio.setEstado("APROBADO");
                convenioRepository.save(convenio);

                // 4. Retorno HTML estético de éxito para el buzón del Jefe de Estudios
                return "<div style='text-align:center; margin-top:50px; font-family:sans-serif; color: #155724; background-color: #d4edda; padding: 20px; border-radius: 5px; max-width: 500px; margin-left: auto; margin-right: auto; border: 1px solid #c3e6cb;'>"
                        + "<h2>✅ Convenio Autorizado</h2>"
                        + "<p>El acuerdo de prácticas <b>" + numeroAcuerdo + "</b> ha sido validado con éxito.</p>"
                        + "<small style='color: #6c757d;'>El estado ha sido actualizado en la base de datos de MongoDB.</small>"
                        + "</div>";
            } else {
                return "<h2 style='text-align:center; color:red; margin-top:50px;'>❌ Error: No se encontró ningún convenio con el Nº Acuerdo: " + numeroAcuerdo + "</h2>";
            }
        } catch (Exception e) {
            return "<h2>❌ Error interno al procesar la aprobación: " + e.getMessage() + "</h2>";
        }
    }

        /**
     * 🟢 ENDPOINT DE MIGRACIÓN UNIFICADO
     * POST -> http://localhost:8080/api/convenios/migrar
     */
    @PostMapping("/migrar")
    public ResponseEntity<Convenio> migrarConvenioCompleto(@RequestBody Convenio dto) {
        // Adaptamos el servicio de migración para que reciba y procese la nueva entidad Convenio directamente
        Convenio resultado = convenioMigrationService.procesarYGuardarConvenio(dto);
        return ResponseEntity.status(HttpStatus.CREATED).body(resultado);
    }

    /**
     * 🌍 ENDPOINT C: ÁMBITO MACRO-CENTRO (Anexo V - Relación de todos los alumnos de todos los convenios)
     * GET -> http://localhost:8080/api/documentos/anexo/macro-global/5
     */
    @GetMapping("/anexo/macro-global/5")
    public ResponseEntity<Documento> descargarAnexoVMacroGlobal() {
        try {
            // 1. Descargamos la colección completa de convenios con sus fotos incrustadas desde MongoDB
            List<Convenio> todosLosConvenios = convenioRepository.findAll();
            
            // 2. Instanciamos un contenedor Convenio ficticio en memoria únicamente para agrupar la ráfaga masiva
            Convenio macroConvenio = new Convenio();
            List<Alumno> rafagaAlumnosGlobal = new ArrayList<>();
            
            for (Convenio c : todosLosConvenios) {
                if (c.getAlumnos() != null) {
                    // Copiamos los alumnos puros directamente a la lista global
                    rafagaAlumnosGlobal.addAll(c.getAlumnos());
                }
            }
            
            // Inyectamos la ráfaga masiva y metadatos generales
            macroConvenio.setAlumnos(rafagaAlumnosGlobal);
            macroConvenio.setNumeroAcuerdo("GLOBAL-CENTRO");
            macroConvenio.setCursoAcademico(todosLosConvenios.isEmpty() ? "-" : todosLosConvenios.get(0).getCursoAcademico());
            
            // ⚡ Sincronizamos variables de Lombok en memoria
            macroConvenio.sincronizarCamposPlanosTemplate();

            // 3. Montamos el contexto apuntando a la plantilla masiva
            String nombrePlantilla = "anexo_5_macro_global.docx";
            java.nio.file.Path baseDir = java.nio.file.Paths.get(System.getProperty("java.io.tmpdir"));
            
            GenerarDocumentoContext ctx = new GenerarDocumentoContext(
                macroConvenio, 
                "ANEXO_5_GLOBAL", 
                nombrePlantilla, 
                baseDir
            );
            
            // 4. Invocación segura al motor de plantillas
            Documento documento = documentoService.generarDocumento(ctx);
            if (documento == null) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
            }
            
            return ResponseEntity.ok()
                .header("Content-Disposition", "attachment; filename=\"Anexo_V_Global_Centro.pdf\"")
                .header("Content-Type", "application/pdf")
                .body(documento);

        } catch (Exception e) {
            System.err.println("❌ Error en el macro-procesamiento del Anexo V Global: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

}
