package es.pulsoft.dao;

import java.util.List;

import javax.transaction.Transactional;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import es.pulsoft.controlador.entity.Estudiante;

/**
 * Clase DAO para gestionar las operaciones relacionadas con la entidad Estudiante.
 * Implementa la interfaz EstudianteDao.
 * Las operaciones incluyen insertar, listar, obtener, eliminar y buscar estudiantes.
 */
@Repository
public class EstudianteDaoClase implements EstudianteDao {

    @Autowired
    private SessionFactory sessionFactory;

    /**
     * Inserta o actualiza un estudiante en la base de datos.
     * 
     * @param estudiante el objeto Estudiante que se va a insertar o actualizar.
     */
    @Override
    @Transactional
    public void insertarEstudiante(Estudiante estudiante) {
        try {
            // Obtiene la sesión actual de Hibernate
            Session session = sessionFactory.getCurrentSession();
            // Guarda o actualiza el estudiante en la base de datos
            session.saveOrUpdate(estudiante);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Obtiene una lista de todos los estudiantes en la base de datos.
     * 
     * @return una lista de objetos Estudiante.
     */
    @Override
    @Transactional
    public List<Estudiante> listarEstudiantes() {
        List<Estudiante> listaEstudiantes = null;
        try {
            // Obtiene la sesión actual de Hibernate
            Session session = sessionFactory.getCurrentSession();
            // Ejecuta la consulta HQL para obtener todos los estudiantes
            listaEstudiantes = session.createQuery("from Estudiante", Estudiante.class).getResultList();
            return listaEstudiantes;
        } catch (Exception e) {
            e.printStackTrace();
            return listaEstudiantes;
        }
    }

    /**
     * Obtiene un estudiante por su ID.
     * 
     * @param id el ID del estudiante a obtener.
     * @return el objeto Estudiante correspondiente al ID proporcionado, o null si no se encuentra.
     */
    @Override
    @Transactional
    public Estudiante obtenerEstudiante(int id) {
        Session session = sessionFactory.getCurrentSession();
        Estudiante estudiante = null;
        try {
            // Obtiene el estudiante por su ID
            estudiante = session.get(Estudiante.class, id);
            return estudiante;
        } catch (Exception e) {
            e.printStackTrace();
            return estudiante;
        }
    }

    /**
     * Elimina un estudiante de la base de datos.
     * 
     * @param id el ID del estudiante a eliminar.
     */
    @Override
    @Transactional
    public void borrarEstudiante(int id) {
        Session session = sessionFactory.getCurrentSession();
        try {
            // Obtiene el estudiante por su ID
            Estudiante estudiante = session.get(Estudiante.class, id);
            // Elimina el estudiante de la base de datos
            session.delete(estudiante);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Realiza una búsqueda de estudiantes basándose en el nombre.
     * 
     * @param valor el valor que se busca en el campo nombre.
     * @return una lista de objetos Estudiante que coinciden con el valor de búsqueda.
     */
    @Override
    @Transactional
    public List<Estudiante> buscar(String valor) {
        Session session = sessionFactory.getCurrentSession();
        List<Estudiante> listaEstudiantes = null;
        try {
            // Realiza la búsqueda por nombre utilizando la consulta HQL
            listaEstudiantes = session.createQuery("from Estudiante where lower(nombre) like :valor", Estudiante.class)
                    .setParameter("valor", valor + "%")
                    .getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return listaEstudiantes;
    }

    /**
     * Realiza una búsqueda de estudiantes basándose en su edad, dentro de un rango de edad.
     * 
     * @param valorMinimo la edad mínima del rango.
     * @param valorMaximo la edad máxima del rango.
     * @return una lista de objetos Estudiante cuya edad está dentro del rango especificado.
     */
    @Override
    @Transactional
    public List<Estudiante> buscarEdad(int valorMinimo, int valorMaximo) {
        Session session = sessionFactory.getCurrentSession();
        List<Estudiante> listaEstudiantes = null;
        try {
            // Realiza la búsqueda por edad utilizando la consulta HQL con un rango de edad
            listaEstudiantes = session.createQuery("from Estudiante where edad between :valorMinimo and :valorMaximo", Estudiante.class)
                    .setParameter("valorMinimo", valorMinimo)
                    .setParameter("valorMaximo", valorMaximo)
                    .getResultList();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return listaEstudiantes;
    }
}
