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.EscuelaBusqueda;
import es.pulsoft.controlador.entity.Director;
import es.pulsoft.controlador.entity.Escuela;
import es.pulsoft.dao.DirectorDao;
import es.pulsoft.dao.EscuelaDao;

/**
 * Controlador encargado de gestionar las operaciones relacionadas con las escuelas:
 * agregar, actualizar, eliminar, mostrar y buscar escuelas.
 */
@Controller
@RequestMapping("/Escuela")
public class EscuelaControlador {

    @Autowired
    private EscuelaDao escuelaDao;

    @Autowired
    private DirectorDao directorDao;

    /**
     * Muestra el formulario para agregar o actualizar una escuela.
     * 
     * @param modelo Modelo para enviar datos a la vista
     * @param modo   Indica si se está en modo "normal" (agregar) o "actualizar"
     * @return Nombre de la vista del formulario
     */
    @GetMapping("/agregarEscuela")
    public String formularioEscuela(Model modelo, String modo) {
        modelo.addAttribute("escuela", new Escuela());
        modelo.addAttribute("modo", modo);
        List<Director> listaDirectores = escuelaDao.obtenerDirectores();
        modelo.addAttribute("listaDirectores", listaDirectores);
        return "escuela/agregarEscuela";
    }

    /**
     * Procesa la solicitud para insertar o actualizar una escuela.
     * 
     * @param escuela   Objeto Escuela con datos del formulario
     * @param resultado Resultado de la validación del formulario
     * @param modo      Modo de operación ("normal" o "actualizar")
     * @param session   Sesión HTTP para almacenar mensajes
     * @param modelo    Modelo para pasar datos a la vista
     * @return Redirección o vista según resultado
     */
    @PostMapping("/agregarEscuela")
    public String insertarEscuela(
            @Valid @ModelAttribute("escuela") Escuela escuela,
            BindingResult resultado,
            @RequestParam String modo,
            HttpSession session,
            Model modelo) {

        modelo.addAttribute("listaDirectores", escuelaDao.obtenerDirectores());
        modelo.addAttribute("modo", modo);

        if (resultado.hasErrors()) {
            return "escuela/agregarEscuela";
        }

        try {
            escuelaDao.insertarEscuela(escuela);
            if (modo.equals("actualizar")) {
                Director director = directorDao.getDirector(escuela.getDirector().getId());
                director.setEscuela(escuela);
                escuela.setDirector(director);
            }

            if (modo.equals("normal")) {
                session.setAttribute("mensaje", "Escuela agregada correctamente");
            } else {
                session.setAttribute("mensaje", "Escuela actualizada correctamente");
            }

            return "redirect:/";

        } catch (Exception e) {
            if (modo.equals("normal")) {
                modelo.addAttribute("error", "Error al agregar la escuela: " + e.getMessage());
            } else {
                modelo.addAttribute("error", "Error al actualizar la escuela: " + e.getMessage());
            }
            return "escuela/agregarEscuela";
        }
    }

    /**
     * Muestra la lista de escuelas en función del modo (ver, actualizar, borrar).
     * 
     * @param modelo Modelo para pasar datos a la vista
     * @param modo   Modo de operación
     * @return Nombre de la vista que muestra las escuelas
     */
    @GetMapping("/mostrarEscuela")
    public String mostrarEscuela(Model modelo, @RequestParam("modo") String modo) {
        try {
            List<Escuela> listaEscuelas = escuelaDao.obternerEscuelas();
            modelo.addAttribute("modo", modo);
            modelo.addAttribute("listaEscuelas", listaEscuelas);
            modelo.addAttribute("escuelaBusqueda", new EscuelaBusqueda());
            return "/escuela/mostrarEscuela";
        } catch (Exception e) {
            return "/escuela/mostrarEscuela";
        }
    }

    /**
     * Elimina una escuela por ID.
     * 
     * @param id     ID de la escuela a eliminar
     * @param modelo Modelo para pasar mensajes a la vista
     * @return Redirección a la vista de escuelas
     */
    @RequestMapping(value = "/borrar", method = { RequestMethod.GET, RequestMethod.POST })
    public String borrarEscuela(@RequestParam("id") int id, Model modelo) {
        try {
            escuelaDao.borrarEscuela(id);
            modelo.addAttribute("mensaje", "Escuela borrada correctamente");
        } catch (Exception e) {
            modelo.addAttribute("error", "Error al borrar escuela");
        }
        return "redirect:/Escuela/mostrarEscuela?modo=borrar";
    }

    /**
     * Muestra el formulario para actualizar una escuela existente.
     * 
     * @param id      ID de la escuela a actualizar
     * @param modo    Modo de operación
     * @param modelo  Modelo para enviar datos a la vista
     * @param session Sesión HTTP para mensajes de error
     * @return Nombre de la vista del formulario
     */
    @GetMapping("/actualizar")
    public String actualizar(@RequestParam("id") int id, String modo, Model modelo, HttpSession session) {
        try {
            Escuela escuela = escuelaDao.obtenerEscuela(id);
            List<Director> listaDirectores = escuelaDao.obtenerDirectores();
            modelo.addAttribute("modo", modo);
            modelo.addAttribute("escuela", escuela);
            Director director = directorDao.getDirector(escuela.getDirector().getId());
            listaDirectores.add(director); // Se asegura de que el director actual esté en la lista
            modelo.addAttribute("listaDirectores", listaDirectores);
            return "escuela/agregarEscuela";
        } catch (Exception e) {
            session.setAttribute("error", "Error al recuperar la escuela");
            return "redirect:/Escuela/mostrarEscuela?modo=actualizar";
        }
    }

    /**
     * Realiza la búsqueda de escuelas según el tipo y valor ingresados.
     * 
     * @param escuelaBusqueda Objeto con criterios de búsqueda
     * @param modo            Modo actual de la vista
     * @param modelo          Modelo para pasar datos a la vista
     * @return Nombre de la vista con resultados
     */
    @GetMapping("/buscar")
    public String buscarEscuelas(@ModelAttribute("escuelaBusqueda") EscuelaBusqueda escuelaBusqueda,
            @RequestParam("modo") String modo,
            Model modelo) {

        try {
            String tipo = escuelaBusqueda.getTipoBusqueda();
            String valor = escuelaBusqueda.getValor();
            List<Escuela> listaEscuelas = escuelaDao.obternerEscuelasBusqueda(tipo, valor);
            modelo.addAttribute("listaEscuelas", listaEscuelas);
            modelo.addAttribute("mensaje", "Hay " + listaEscuelas.size() + " que coinciden con la búsqueda");
        } catch (Exception e) {
            modelo.addAttribute("error", "Error en la búsqueda");
        }

        return "/escuela/mostrarEscuela";
    }
}
