package es.pulsoft.controlador;

import java.util.List;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import es.pulsoft.controlador.dto.EstudianteBusqueda;
import es.pulsoft.controlador.entity.Estudiante;
import es.pulsoft.dao.EstudianteDao;

/**
 * Controlador para gestionar operaciones relacionadas con estudiantes.
 * Permite agregar, actualizar, borrar, listar y buscar estudiantes.
 */
@Controller
@RequestMapping("/Estudiante")
public class EstudianteControlador {

    @Autowired
    private EstudianteDao estudianteDao;

    /**
     * Muestra el formulario para agregar un nuevo estudiante.
     * 
     * @param modelo Objeto Model para enviar datos a la vista.
     * @param modo   Modo en que se llama (normal o actualizar).
     * @return Nombre de la vista del formulario.
     */
    @GetMapping("/agregarEstudiante")
    public String formularioEstudiante(Model modelo, String modo) {
        modelo.addAttribute("estudiante", new Estudiante());
        modelo.addAttribute("modo", modo);
        return "estudiante/agregarEstudiante";
    }

    /**
     * Guarda un nuevo estudiante o actualiza uno existente, según el modo.
     * 
     * @param estudiante Objeto Estudiante a guardar.
     * @param result     Resultado de validación.
     * @param modo       Modo (normal o actualizar).
     * @param session    Sesión HTTP para guardar mensajes.
     * @param modelo     Objeto Model para enviar datos a la vista.
     * @return Redirección a la raíz o al formulario en caso de error.
     */
    @PostMapping("/agregarEstudiante")
    public String guardarDirector(@Valid @ModelAttribute("estudiante") Estudiante estudiante,
                                  BindingResult result,
                                  @RequestParam String modo,
                                  HttpSession session,
                                  Model modelo) {
        modelo.addAttribute("modo", modo);
        try {
            if (result.hasErrors()) {
                // Si hay errores de validación, vuelve al formulario
                return "estudiante/agregarEstudiante";
            } else {
                estudianteDao.insertarEstudiante(estudiante);
                // Define el mensaje según el modo
                if (modo.contentEquals("normal")) {
                    session.setAttribute("mensaje", "Estudiante guardado correctamente");
                } else {
                    session.setAttribute("mensaje", "Estudiante actualizado correctamente");
                }
                return "redirect:/";
            }
        } catch (Exception e) {
            // Manejo de errores en la inserción o actualización
            if (modo.contentEquals("normal")) {
                session.setAttribute("error", "Error al guardar el estudiante");
            } else {
                session.setAttribute("error", "Error al actualizar el estudiante");
            }
            return "redirect:/";
        }
    }

    /**
     * Muestra una lista de todos los estudiantes registrados.
     * 
     * @param estudiante Objeto usado para el formulario.
     * @param modelo     Modelo para la vista.
     * @param modo       Modo en que se llama la vista.
     * @param session    Sesión para mostrar mensajes si existen.
     * @return Nombre de la vista con la lista de estudiantes.
     */
    @GetMapping("/mostrarEstudiante")
    public String listarEstudiantes(@ModelAttribute("estudiante") Estudiante estudiante, Model modelo, String modo, HttpSession session) {

        // Recuperar mensaje de sesión si existe
        String mensaje = (String) session.getAttribute("mensaje");
        if (mensaje != null) {
            modelo.addAttribute("mensaje", mensaje);
            session.removeAttribute("mensaje");
        }

        List<Estudiante> listaEstudiantes = estudianteDao.listarEstudiantes();
        modelo.addAttribute("listaEstudiantes", listaEstudiantes);
        modelo.addAttribute("modo", modo);
        modelo.addAttribute("estudianteBusqueda", new EstudianteBusqueda());

        return "/estudiante/mostrarEstudiante";
    }

    /**
     * Carga un estudiante específico para ser actualizado.
     * 
     * @param id      ID del estudiante a actualizar.
     * @param modelo  Modelo para pasar datos a la vista.
     * @param modo    Modo de operación (actualizar).
     * @param session Sesión HTTP para mensajes de error.
     * @return Vista del formulario de estudiante.
     */
    @GetMapping("/actualizar")
    public String actualizarEstudiante(@RequestParam("id") int id, Model modelo, String modo, HttpSession session) {
        try {
            Estudiante estudiante = estudianteDao.obtenerEstudiante(id);
            modelo.addAttribute("estudiante", estudiante);
            modelo.addAttribute("modo", modo);
            return "/estudiante/agregarEstudiante";
        } catch (Exception e) {
            session.setAttribute("error", "Error al recuperar al estudiante");
            return "redirect:/";
        }
    }

    /**
     * Borra un estudiante dado su ID.
     * 
     * @param id     ID del estudiante a borrar.
     * @param modelo Modelo para agregar mensajes.
     * @return Redirección a la vista de listado.
     */
    @RequestMapping(value = "/borrar", method = { RequestMethod.GET, RequestMethod.POST })
    public String borrarEstudiante(@RequestParam("id") int id, Model modelo) {
        try {
            estudianteDao.borrarEstudiante(id);
            modelo.addAttribute("mensaje", "Estudiante borrado correctamente");
        } catch (Exception e) {
            modelo.addAttribute("error", "Error al borrar al estudiante");
        }
        return "redirect:/Estudiante/mostrarEstudiante?modo=borrar";
    }

    /**
     * Busca estudiantes según el tipo de búsqueda (nombre o edad).
     * 
     * @param estudianteBusqueda Parámetros de búsqueda.
     * @param session            Sesión HTTP para mensajes.
     * @param modelo             Modelo para enviar datos a la vista.
     * @param modo               Modo actual de visualización.
     * @return Vista con los resultados de búsqueda.
     */
    @GetMapping("/buscar")
    public String buscarEstudiante(@ModelAttribute("estudianteBuesqueda") EstudianteBusqueda estudianteBusqueda,
                                   HttpSession session,
                                   Model modelo,
                                   String modo) {

        String tipo = estudianteBusqueda.getTipoBusqueda();
        List<Estudiante> listaEstudiantes = null;

        // Filtrar según el tipo de búsqueda seleccionado
        switch (tipo) {
            case "nombre": {
                String valor = estudianteBusqueda.getValor();
                listaEstudiantes = estudianteDao.buscar(valor);
                break;
            }
            case "edad": {
                int valorMinimo = estudianteBusqueda.getEdadMinima();
                int valorMaximo = estudianteBusqueda.getEdadMaxima();
                listaEstudiantes = estudianteDao.buscarEdad(valorMinimo, valorMaximo);
                break;
            }
        }

        // Enviar los resultados a la vista
        modelo.addAttribute("modo", modo);
        modelo.addAttribute("estudianteBusqueda", estudianteBusqueda);
        modelo.addAttribute("listaEstudiantes", listaEstudiantes);
        session.setAttribute("mensaje", listaEstudiantes.size() + " estudiantes coinciden con la búsqueda");

        return "estudiante/mostrarEstudiante";
    }

}
