package mx.gob.jumapacelaya.services;

import mx.gob.jumapacelaya.models.*;
import mx.gob.jumapacelaya.models.encuestas.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Service
public class DatabaseService {

    private static final Logger logger = LoggerFactory.getLogger(DatabaseService.class);

    @Value("${db.url}")
    private String dbUrl;
    @Value("${db.user}")
    private String dbUser;
    @Value("${db.pass}")
    private String dbPass;

    private Connection getMysqlConnection() throws SQLException {
        return DriverManager.getConnection(dbUrl, dbUser, dbPass);
    }

    /*private Connection getOracleConnection() throws SQLException {
        String url = "jdbc:oracle:thin:@//svradminfinan:1521/admfinpdb.JUMAPACELAYA.GOB.MX";
        String user = "Finanzas";
        String pass = "finanzas";

        return DriverManager.getConnection(url, user, pass);

    }*/

    // Método para obtener los tipos de mantenimientos
    public List<TiposMantenimiento> getTiposDeMantenimientos() {
        List<TiposMantenimiento> tiposDeMantenimientos = new ArrayList<>();
        String query = "SELECT tipomantid, nombre FROM TIPOMANT";

        try (Connection connection = getMysqlConnection();
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query)) {

            while (resultSet.next()) {
                TiposMantenimiento tipo = new TiposMantenimiento(
                        resultSet.getString("tipomantid"),
                        resultSet.getString("nombre")
                );
                tiposDeMantenimientos.add(tipo);
            }
        } catch (SQLException e) {
            logger.error("Error al obtener tipos de mantenimientos: ", e);
        }
        return tiposDeMantenimientos;
    }

    // Método para obtener las nomenclaturas
    public String getNomenclatura(String tipoMantenimiento) {
        String nomenclatura = "";
        String query = "SELECT nomenclatura FROM TIPOMANT where TIPOMANTID = ?";

        try (Connection connection = getMysqlConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(query)) {
            preparedStatement.setString(1, tipoMantenimiento);

            try (ResultSet resultSet = preparedStatement.executeQuery()) {
                if (resultSet.next()) {
                    nomenclatura = resultSet.getString("nomenclatura");
                }
            }

        } catch (SQLException e) {
            logger.error("Error al obtener nomenclatura: ", e);
        }
        return nomenclatura;
    }

    /* -------------- Metodo para obtener a los usuarios ---------------- */
    public List<Usuario> getUsuarios() {
        List<Usuario> usuarios = new ArrayList<>();
        String query = "SELECT u.* \n" +
                "FROM USUARIOS u";

        try (Connection connection = getMysqlConnection();
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query)) {

            while (resultSet.next()) {
                Usuario usuario = new Usuario(
                        resultSet.getString("empleadoid"),
                        resultSet.getString("nombre"),
                        resultSet.getString("email")
                );
                usuarios.add(usuario);
            }
        } catch (SQLException e) {
            logger.error("Error al obtener usuarios: ", e);
        }
        return usuarios;
    }

    /* -------------- Metodo para obtener los departamentos ---------------- */
    public List<DepartamentosModel> getDepartamentos() {
        List<DepartamentosModel> departamentos = new ArrayList<>();
        String query = "select DEPARTAMENTOID, DESCRIPCION from DEPARTAMENTOS";

        try (Connection connection = getMysqlConnection();
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query)) {

            while (resultSet.next()) {
                DepartamentosModel departamentosModel = new DepartamentosModel(
                        resultSet.getString("departamentoid"),
                        resultSet.getString("descripcion")
                );
                departamentos.add(departamentosModel);
            }
        } catch (SQLException e) {
            logger.error("Error al obtener departamentos: ", e);
        }
        return departamentos;
    }

    /* -------------- Metodo para obtener los tipos de hardware ---------------- */
    public List<TiposHardware> getTiposHardware() {
        List<TiposHardware> tiposHardware = new ArrayList<>();
        String query = "select TIPOHARDWAREID, DESCRIPCION from TIPOSHARDWARE";

        try (Connection connection = getMysqlConnection();
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query)) {

            while (resultSet.next()) {
                TiposHardware tiposHardwareModel = new TiposHardware(
                        resultSet.getString("tipohardwareid"),
                        resultSet.getString("descripcion")
                );
                tiposHardware.add(tiposHardwareModel);
            }
        } catch (SQLException e) {
            logger.error("Error al obtener tipos de hardware: ", e);
        }
        return tiposHardware;
    }

    /* ----------------Obtener el Plan Anual de Mantenimiento ---------------- */
    public List<PlanAnual> getPlanAnual() {
        List<PlanAnual> planAnualList = new ArrayList<>();
        String query = """
                SELECT p.plananualid, p.nomEquipo, p.area,
                        p.monitor, p.teclado, p.mouse, p.regulador,
                        p.cpu, p.impresora, p.miniPrint, p.laptop, p.escaner,
                        p.fechaprog, m.fecha AS fechaMantenimiento,
                        me.NOMBRE AS MESPLANEADO, p.tecnicosmt, p.estado,
                        COALESCE(v.SITUACION, 'NO REALIZADO') AS SITUACION,
                        m.ENCUESTA\s
                FROM PLANANUAL p
                LEFT JOIN MANTENIMIENTOS m ON p.plananualid = m.plananualid
                LEFT JOIN MESES me ON p.MESID  = me.MESID
                LEFT JOIN VW_SITUACION_MANTENIMIENTO v ON v.PLANANUALID = p.PLANANUALID
                ORDER BY p.FECHAPROG ASC
        """;

        try (Connection connection = getMysqlConnection();
            Statement statement = connection.createStatement();
            ResultSet resultSet = statement.executeQuery(query)) {

            while (resultSet.next()) {
                PlanAnual planAnual = new PlanAnual(
                        resultSet.getInt("plananualid"),
                        resultSet.getString("nomEquipo"),
                        resultSet.getString("area"),
                        resultSet.getBoolean("monitor"),
                        resultSet.getBoolean("teclado"),
                        resultSet.getBoolean("mouse"),
                        resultSet.getBoolean("regulador"),
                        resultSet.getBoolean("cpu"),
                        resultSet.getBoolean("impresora"),
                        resultSet.getBoolean("miniPrint"),
                        resultSet.getBoolean("laptop"),
                        resultSet.getBoolean("escaner"),
                        resultSet.getDate("fechaprog").toLocalDate(), // Cambiado a LocalDate
                        resultSet.getDate("fechaMantenimiento") != null ? resultSet.getDate("fechaMantenimiento").toLocalDate() : null, // Cambiado a LocalDate
                        resultSet.getString("mesplaneado"),
                        resultSet.getString("tecnicosmt"),
                        resultSet.getString("estado"),
                        resultSet.getString("SITUACION"),
                        resultSet.getString("ENCUESTA") == null ? "N/A" : resultSet.getString("ENCUESTA")
                );
                planAnualList.add(planAnual);
            }
        } catch (SQLException e) {
            logger.error("Error al obtener plan anual: ", e);
        }
        return planAnualList;
    }

    /* ----------------Obtener el Plan Anual de Mantenimiento por ID ---------------- */
    public PlanAnual getPlanAnualPorId(int id) {
        String query = """
                SELECT p.plananualid, p.nomEquipo, p.area,
                            p.monitor, p.teclado, p.mouse, p.regulador,
                            p.cpu, p.impresora, p.miniPrint, p.laptop, p.escaner,
                            p.fechaprog, m.fecha AS fechaMantenimiento,
                            me.NOMBRE AS MESPLANEADO, p.tecnicosmt, p.estado,
                            COALESCE(v.SITUACION, 'NO REALIZADO') AS SITUACION,
                            m.ENCUESTA
            FROM PLANANUAL p
            LEFT JOIN MANTENIMIENTOS m ON p.plananualid = m.plananualid
            LEFT JOIN MESES me ON p.MESID  = me.MESID
            LEFT JOIN VW_SITUACION_MANTENIMIENTO v ON v.PLANANUALID = p.PLANANUALID
            WHERE p.plananualid = ?
            """;
        try (Connection connection = getMysqlConnection();
             PreparedStatement statement = connection.prepareStatement(query)) {

            statement.setInt(1, id);
            try (ResultSet resultSet = statement.executeQuery()) {
                if (resultSet.next()) {
                    return new PlanAnual(
                            resultSet.getInt("plananualid"),
                            resultSet.getString("nomEquipo"),
                            resultSet.getString("area"),
                            resultSet.getBoolean("monitor"),
                            resultSet.getBoolean("teclado"),
                            resultSet.getBoolean("mouse"),
                            resultSet.getBoolean("regulador"),
                            resultSet.getBoolean("cpu"),
                            resultSet.getBoolean("impresora"),
                            resultSet.getBoolean("miniPrint"),
                            resultSet.getBoolean("laptop"),
                            resultSet.getBoolean("escaner"),
                            resultSet.getDate("fechaprog").toLocalDate(), // Cambiado a LocalDate
                            resultSet.getDate("fechaMantenimiento") != null ? resultSet.getDate("fechaMantenimiento").toLocalDate() : null, // Cambiado a LocalDate
                            resultSet.getString("mesplaneado"),
                            resultSet.getString("tecnicosmt"),
                            resultSet.getString("estado"),
                            resultSet.getString("SITUACION"),
                            resultSet.getString("encuesta")
                    );
                }
            }
        } catch (SQLException e) {
            logger.error("Error al obtener plan anual por id: ", e);
        }
        return null;
    }

     /* ----------------Obtener detalles del mantenimiento ---------------- */
    public DetalleMantenimientoModel getDetalleMantenimientoPorPlanAnualId(int planAnualId) {
        String query = "SELECT\n" +
                "    m.MANTENIMIENTOID AS ID,\n" +
                "    p.PLANANUALID,\n" +
                "    t.NOMBRE AS TIPO,\n" +
                "    d.DESCRIPCION AS DEPARTAMENTO,\n" +
                "    u.NOMBRE AS USUARIO,\n" +
                "    v.FECHAPROG,\n" +
                "    v.FECHAREALIZADO,\n" +
                "    NOMBREEQUIPO,\n" +
                "    FORMAMANT,\n" +
                "    FIRMAUSUARIO,\n" +
                "    FIRMASMT,\n" +
                "    FIRMAGCIA,\n" +
                "    v.SITUACION\n" +
                "FROM MANTENIMIENTOS m\n" +
                "INNER JOIN TIPOMANT t ON m.TIPOMANTID = t.TIPOMANTID\n" +
                "INNER JOIN DEPARTAMENTOS d ON m.DEPARTAMENTOID = d.DEPARTAMENTOID\n" +
                "INNER JOIN USUARIOS u ON u.EMPLEADOID = m.EMPLEADOID\n" +
                "INNER JOIN PLANANUAL p ON m.PLANANUALID = p.PLANANUALID\n" +
                "INNER JOIN PLANANUAL pa ON m.PLANANUALID = pa.PLANANUALID\n" +
                "INNER JOIN VW_SITUACION_MANTENIMIENTO v ON v.MANTENIMIENTOID = m.MANTENIMIENTOID\n" +
                "WHERE p.PLANANUALID = ?";

        try (Connection connection = getMysqlConnection();
            PreparedStatement statement = connection.prepareStatement(query)) {

            statement.setInt(1, planAnualId);

            try (ResultSet rs = statement.executeQuery()) {
                if (rs.next()) {
                    return new DetalleMantenimientoModel(
                        rs.getInt("ID"),
                        rs.getInt("PLANANUALID"),
                        rs.getString("TIPO"),
                        rs.getString("DEPARTAMENTO"),
                        rs.getString("USUARIO"),
                        rs.getDate("FECHAPROG").toLocalDate(),
                        rs.getDate("FECHAREALIZADO").toLocalDate(),
                        rs.getString("NOMBREEQUIPO"),
                        rs.getString("FORMAMANT"),
                        rs.getString("FIRMAUSUARIO"),
                        rs.getString("FIRMASMT"),
                        rs.getString("FIRMAGCIA"),
                            rs.getString("SITUACION")
                    );
                }
            }
        } catch (SQLException e) {
            logger.error("Error al obtener detalles del mantenimiento por plan anual id: ", e);
        }

        return null;
    }

    /* ----------------Obtener mantenimientos sin encuesta respondida por periodo ---------------- */
    public List<MantenimientosSinEncuesta> getEncuestPendientes(String mes, int anio) {
        List<MantenimientosSinEncuesta> lista = new ArrayList<>();
        String query = """
                SELECT DISTINCT
                	m.MANTENIMIENTOID	MANTID,
                	m.PLANANUALID	PLANID,
                	m.FECHA,
                	ms.NOMBRE	PERIODO,
                	t.NOMBRE	TIPOMANT,
                	d.DESCRIPCION	DEPTO,
                	u.NOMBRE	NOMUSUARIO,
                	u.EMAIL,
                	m.ENCUESTA,
                	CASE WHEN e.TOKEN IS NOT NULL THEN 1 ELSE 0 END AS TIENE_TOKEN
                FROM MANTENIMIENTOS m
                JOIN TIPOMANT t
                	ON t.TIPOMANTID = m.TIPOMANTID
                JOIN DEPARTAMENTOS d
                	on d.DEPARTAMENTOID = m.DEPARTAMENTOID
                JOIN USUARIOS u
                	on u.EMPLEADOID = m.EMPLEADOID
                JOIN PLANANUAL p
                	ON p.PLANANUALID = m.PLANANUALID
                JOIN MESES ms
                	ON ms.MESID = p.MESID
                LEFT JOIN ENCUESTATOKENS e 
                    ON e.MANTENIMIENTOID = m.MANTENIMIENTOID
                WHERE
                	 m.TIPOMANTID = 1
                	AND m.PLANANUALID IS NOT NULL
                	AND UPPER(ms.NOMBRE) = UPPER(?)
                	AND EXTRACT(YEAR FROM m.FECHA) = ?
                """;

        try(Connection connection = getMysqlConnection();
            PreparedStatement stmt =  connection.prepareStatement(query)) {

            stmt.setString(1, mes.toUpperCase());
            stmt.setInt(2, anio);

            ResultSet rs = stmt.executeQuery();

            while (rs.next()) {
                lista.add(new MantenimientosSinEncuesta(
                        rs.getInt("MANTID"),
                        rs.getInt("PLANID"),
                        rs.getDate("FECHA").toLocalDate(),
                        rs.getString("PERIODO"),
                        rs.getString("TIPOMANT"),
                        rs.getString("DEPTO"),
                        rs.getString("NOMUSUARIO"),
                        rs.getString("EMAIL"),
                        rs.getString("ENCUESTA"),
                        rs.getBoolean("TIENE_TOKEN")
                ));
            }
        } catch (SQLException e) {
            logger.error("Error al obtener mantenimientos sin encuesta respondida por periodo: ", e);
        }

        return lista;
    }

     /* ----------------Obtener detalles del hardaware por ID ---------------- */
    public List<HardwareDetalle> getHardwaredetallePorMantId(int mantenimientoId) {
        List<HardwareDetalle> detalles = new ArrayList<>();
        String query = "SELECT  h.MANTENIMIENTOID, h.HARDWAREDETID, t.DESCRIPCION, h.MODELO, h.NUMSERIE, h.PLACA\r\n" + //
                        "FROM HARDWAREDET h\r\n" + //
                        "INNER JOIN TIPOSHARDWARE t ON h.TIPOHARDWAREID = t.TIPOHARDWAREID \r\n" + //
                        "WHERE h.MANTENIMIENTOID = ?";

        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(query)) {

            stmt.setInt(1, mantenimientoId);
            ResultSet rs = stmt.executeQuery();

            while (rs.next()) {
                HardwareDetalle detalle = new HardwareDetalle(
                    rs.getInt("MANTENIMIENTOID"),
                    rs.getInt("HARDWAREDETID"),
                    rs.getString("DESCRIPCION"),
                    rs.getString("MODELO"),
                    rs.getString("NUMSERIE"),
                    rs.getString("PLACA")
                );
                detalles.add(detalle);
            }

        } catch (SQLException e) {
            logger.error("Error al obtener detalles del hardaware por ID: ", e);
        }
        return detalles;
    }

     /* ---------------- Obtener las actualizaciones de seguridad ---------------- */
    public List<ActualizacioneSeguridadModel> getActualizacionesSeg(int mantenimientoId) {
        List<ActualizacioneSeguridadModel> actualizaciones = new ArrayList<>();
        String query = "SELECT *\r\n" + //
                        "FROM ACTUALIZACIONESSEG a\r\n" + //
                        "WHERE a.MANTENIMIENTOID = ?";

        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(query)) {

                stmt.setInt(1, mantenimientoId);
                ResultSet rs = stmt.executeQuery();

                while (rs.next()) {
                    ActualizacioneSeguridadModel actualizacion = new ActualizacioneSeguridadModel(
                        rs.getInt("ACTUALIZACIONSEGID"),
                        rs.getString("DESCRIPCION"),
                        rs.getString("OTRASACTUALIZACIONES"),
                        rs.getInt("MANTENIMIENTOID")
                    );
                    actualizaciones.add(actualizacion);
                }

            } catch (SQLException e) {
                logger.error("Error al obtener las actualizaciones de seguridad: ", e);
            }
            return actualizaciones;
    }

    /* ---------------- Obtener los mantenimientos correctivos ---------------- */
    public List<MantCorrectivosModel> getMantenimientosCorrectivos(int tipomantId) {
        List<MantCorrectivosModel> mantCorrectivos = new ArrayList<>();
        String query = "select\n" +
                "\tm.MANTENIMIENTOID,\n" +
                "\tm.FECHA,\n" +
                "\tt.NOMBRE TIPO,\n" +
                "\td.DESCRIPCION AREA,\n" +
                "\tu.NOMBRE,\n" +
                "\tCASE\n" +
                "\t\tWHEN formamant = 'M' then 'MANUAL'\n" +
                "\t\tELSE 'REMOTO'\n" +
                "\tEND as FORMA,\n" +
                "\tm.NOMBREEQUIPO,\n" +
                "\tm.REPARACION\n" +
                "from MANTENIMIENTOS m\n" +
                "inner join TIPOMANT t on t.TIPOMANTID = m.TIPOMANTID\n" +
                "inner join DEPARTAMENTOS d on d.DEPARTAMENTOID = m.DEPARTAMENTOID\n" +
                "inner join USUARIOS u on u.EMPLEADOID = m.EMPLEADOID\n" +
                "where m.TIPOMANTID = ?";

        try (Connection conn = getMysqlConnection();
            PreparedStatement statement = conn.prepareStatement(query)) {

            statement.setInt(1, tipomantId);
            try (ResultSet rs = statement.executeQuery()) {
                while (rs.next()) {
                    MantCorrectivosModel model = new MantCorrectivosModel(
                            rs.getInt("MANTENIMIENTOID"),
                            rs.getDate("FECHA").toLocalDate(),
                            rs.getString("TIPO"),
                            rs.getString("AREA"),
                            rs.getString("NOMBRE"),
                            rs.getString("FORMA"),
                            rs.getString("NOMBREEQUIPO"),
                            rs.getString("REPARACION")
                    );
                    mantCorrectivos.add(model);
                }
            }
        } catch (SQLException e) {
            logger.error("Error al obtener los mantenimientos correctivos: ", e);
        }
        return mantCorrectivos;
    }

    /*-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<()*/
    /*-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<()*/
    /*-=iii=<() *-=iii=<() *-=iii=<() *-=iii=<()*/
    /*-=iii=<() *-=iii=<() *-=iii=<()*/
    /*-=iii=<() *-=iii=<()*/
    /* ( ͡° ͜ʖ ͡°) Metodos para insetar en la BD ( ͡° ͜ʖ ͡°) ( ͡° ͜ʖ ͡°) Metodos para insetar en la BD ( ͡° ͜ʖ ͡°) ( ͡° ͜ʖ ͡°) Metodos para insetar en la BD ( ͡° ͜ʖ ͡°) */
    // INSERTAR EN TABLA: MANTENIMINETOS
    public int insertarMantenimiento(LocalDate fecha, String tipoMantId, String departamentoId, String empleadoId,
                                    String formaMant, String equipoId, String userSignatureBase64,
                                    String smtSignatureBase64, String planAnualId, String justificacion, String reparacion) {

        String query = "INSERT INTO MANTENIMIENTOS (fecha, tipoMantId, departamentoId, empleadoId, formaMant, nombreequipo," +
                " firmaUsuario, firmaSmt, planAnualId, justificacion, reparacion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

        String updateStatusQuery = "UPDATE PLANANUAL SET estado = 'REALIZADO' WHERE planAnualId = ?";

        int nuevoId = -1;
        Connection connection = null;

        try {
            connection = getMysqlConnection();

            if (connection == null) {
                throw new SQLException("No se pudo establecer la conexion con la base de datos.");
            }


            connection.setAutoCommit(false);

            // Paso 1: primero inserta el mantenimiento
            try (PreparedStatement preparedStatement = connection.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)) {

                preparedStatement.setDate(1, Date.valueOf(fecha));
                preparedStatement.setLong(2, Long.parseLong(tipoMantId));
                preparedStatement.setString(3, departamentoId);
                preparedStatement.setLong(4, Long.parseLong(empleadoId));
                preparedStatement.setString(5, formaMant);
                preparedStatement.setString(6, equipoId);

                if (userSignatureBase64 != null) {
                    preparedStatement.setString(7, userSignatureBase64);
                } else {
                    preparedStatement.setNull(7, Types.VARCHAR);
                }

                if (smtSignatureBase64 != null) {
                    preparedStatement.setString(8, smtSignatureBase64);
                } else {
                    preparedStatement.setNull(8, Types.VARCHAR);
                }

                if (planAnualId != null && !planAnualId.isEmpty()) {
                    preparedStatement.setLong(9, Long.parseLong(planAnualId));
                } else {
                    preparedStatement.setNull(9, Types.BIGINT);
                }
                preparedStatement.setString(10, justificacion);
                preparedStatement.setString(11, reparacion);

                preparedStatement.executeUpdate();

                try (ResultSet rs = preparedStatement.getGeneratedKeys()) {
                    if (rs.next()) {
                        nuevoId = rs.getInt(1);
                    }
                }
            }

            // Paso 2: Si se inserto el mantenimiento, se actualiza el estado en MTTOPROGRAMADOS
            if (nuevoId != -1) {
                try (PreparedStatement updateStatement = connection.prepareStatement(updateStatusQuery)) {
                    updateStatement.setString(1, planAnualId);
                    updateStatement.executeUpdate();
                }
            }

            // Confirmar la transaccion si ambos pasos son exitosos
            connection.commit();

        } catch (SQLException e) {
            logger.error("Error al insertar mantenimiento: ", e);
            // En caso de error, se hace rollback
            if (connection != null) {
                try {
                    connection.rollback();
                } catch (SQLException rollbackEx) {
                    logger.error("Error al hacer rollback: ", rollbackEx);
                }
            }
        } finally {
            // Cerrar la conexion
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException closeEx) {
                    System.err.println("Error al cerrar la conexion: " + closeEx.getMessage());
                }
            }
        }

        return nuevoId;
    }
    /*( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■)( •_•)>⌐■-■ (⌐■_■) */
    /* ˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀˁ˚ᴥ˚ˀ */

    // INSERTAR EN LA TABLA: HARDWAREDET
    public boolean insertarHardware(String tipoHardwareId, String numSerie, String modelo, String placa, int mantenimientoId) {
        String query = "INSERT INTO HARDWAREDET (tipoHardwareId, numSerie, modelo, placa, mantenimientoId) VALUES (?, ?, ?, ?, ?)";
        boolean isInserted = false;

        try (Connection connection = getMysqlConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(query)) {

            preparedStatement.setInt(1, Integer.parseInt(tipoHardwareId));
            preparedStatement.setString(2, numSerie);
            preparedStatement.setString(3, modelo);
            preparedStatement.setString(4, placa);
            preparedStatement.setInt(5, mantenimientoId);

            int rowsAffected = preparedStatement.executeUpdate();
            isInserted = rowsAffected > 0;
        } catch (SQLException e) {
            logger.error("Error al insertar hardware: ", e);
        }
        return isInserted;
    }

    public int getUltimoMantenimientoId() {
        int ultimoId = -1;
        try (Connection connection = getMysqlConnection()) {
            String query = "SELECT MAX(mantenimientoid) FROM MANTENIMIENTOS";
            try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
                ResultSet resultSet = preparedStatement.executeQuery();
                if (resultSet.next()) {
                    ultimoId = resultSet.getInt(1);
                }
            }
        } catch (SQLException e) {
            logger.error("Error al obtener el ultimo id de mantenimiento: ", e);
        }
        return ultimoId;
    }

    // INSERTAR EN LA TABLA: ACTUALIZACIONESSEG
    public boolean insertActualizacionSeg(String descripcion, String otras, int mantenimientoId) {
        String query = "INSERT INTO ACTUALIZACIONESSEG (descripcion, otrasactualizaciones, mantenimientoid) VALUES (?, ?, ?)";

        try (Connection connection = getMysqlConnection();
            PreparedStatement preparedStatement = connection.prepareStatement(query)) {

            preparedStatement.setString(1, descripcion);
            preparedStatement.setString(2, otras);
            preparedStatement.setInt(3, mantenimientoId);

            int rowsInserted = preparedStatement.executeUpdate();
            return rowsInserted > 0;
        } catch (SQLException e) {
            System.err.println("Error al insertar actualizacionSeg: " + e.getMessage());
            return false;
        }
    }

    // INSERTAR ARCHIVO EXCEL EN LA TABLA: PLANANUAL
    public void insertarDesdeExcel(InputStream inputStream) {
        String query = "INSERT INTO PLANANUAL (NOMEQUIPO, AREA, MONITOR, TECLADO, MOUSE, " +
                "REGULADOR, CPU, IMPRESORA, MINIPRINT, LAPTOP, ESCANER, FECHAPROG, TECNICOSMT, ESTADO) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

        try (Connection connection = getMysqlConnection();
             //FileInputStream file = new FileInputStream(rutaArchivoExcel);
            Workbook workbook = new XSSFWorkbook(inputStream)) {

            Sheet sheet = workbook.getSheetAt(0); // Primera hoja del archivo Excel

            for (Row row : sheet) {
                if (row.getRowNum() == 0) continue; // Saltar la primera fila si contiene encabezados

                try {
                    // Leer cada celda de la fila según el índice correcto
                    String nomequipo = getStringCellValue(row.getCell(0)); // Columna 1
                    String area = getStringCellValue(row.getCell(1)); // Columna 2
                    boolean monitor = getBooleanCellValue(row.getCell(2)); // Columna 3
                    boolean teclado = getBooleanCellValue(row.getCell(3)); // Columna 4
                    boolean mouse = getBooleanCellValue(row.getCell(4)); // Columna 5
                    boolean regulador = getBooleanCellValue(row.getCell(5)); // Columna 6
                    boolean cpu = getBooleanCellValue(row.getCell(6)); // Columna 7
                    boolean impresora = getBooleanCellValue(row.getCell(7)); // Columna 8
                    boolean miniprint = getBooleanCellValue(row.getCell(8)); // Columna 9
                    boolean laptop = getBooleanCellValue(row.getCell(9)); // Columna 10
                    boolean escaner = getBooleanCellValue(row.getCell(10)); // Columna 11

                    // Leer la fecha de la columna correcta
                    Date fechaprog = getDateCellValue(row.getCell(11)); // Columna 12
                    String tecnicosmt = getStringCellValue(row.getCell(12)); // Columna 13
                    String estado = getStringCellValue(row.getCell(13)); // Columna 14
                    Date fecharealizado = getDateCellValue(row.getCell(14)); // Columna 15

                    // Insertar datos en la base de datos
                    try (PreparedStatement preparedStatement = connection.prepareStatement(query)) {
                        preparedStatement.setString(1, nomequipo);
                        preparedStatement.setString(2, area);
                        preparedStatement.setBoolean(3, monitor);
                        preparedStatement.setBoolean(4, teclado);
                        preparedStatement.setBoolean(5, mouse);
                        preparedStatement.setBoolean(6, regulador);
                        preparedStatement.setBoolean(7, cpu);
                        preparedStatement.setBoolean(8, impresora);
                        preparedStatement.setBoolean(9, miniprint);
                        preparedStatement.setBoolean(10, laptop);
                        preparedStatement.setBoolean(11, escaner);

                        // Manejo de fechas
                        if (fechaprog != null) {
                            preparedStatement.setDate(12, new java.sql.Date(fechaprog.getTime()));
                        } else {
                            preparedStatement.setNull(12, java.sql.Types.DATE); // Manejo de valor nulo
                        }

                        preparedStatement.setString(13, tecnicosmt);
                        preparedStatement.setString(14, estado);

                        preparedStatement.executeUpdate();
                    }
                } catch (Exception e) {
                    System.err.println("Error procesando la fila " + row.getRowNum() + ": " + e.getMessage());
                }
            }

            System.out.println("Datos insertados desde Excel con éxito en PLANANUAL.");
        } catch (IOException e) {
            System.err.println("Error al leer el archivo Excel: " + e.getMessage());
        } catch (SQLException e) {
            System.err.println("Error al insertar datos en la BD: " + e.getMessage());
        }
    }

    // INSERTAR NUEVO EQUIPO INDIVIDUAL EN PLANANUAL
    public void insertarNuevoEquipo(String nomequipo, String area, boolean monitor, boolean teclado,
                                     boolean mouse, boolean regulador, boolean cpu, boolean impresora,
                                     boolean miniprint, boolean laptop, boolean escaner, Date fechaprog,
                                     String tecnicosmt, String estado, Integer mesId) {

        String query = "INSERT INTO PLANANUAL (NOMEQUIPO, AREA, MONITOR, TECLADO,MOUSE, REGULADOR,\n" +
                    "CPU, IMPRESORA, MINIPRINT, LAPTOP, ESCANER, FECHAPROG,\n" +
                    "TECNICOSMT, ESTADO, MESID)\n" +
                "VALUES (?, ?,\n" +
                    "?, ?, ?, ?, ?, ?, ?, ?, ?,\n" +
                    "?, ?, ?, ?)";

        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(query)) {

            stmt.setString(1, nomequipo);
            stmt.setString(2, area);
            stmt.setBoolean(3, monitor);
            stmt.setBoolean(4, teclado);
            stmt.setBoolean(5, mouse);
            stmt.setBoolean(6, regulador);
            stmt.setBoolean(7, cpu);
            stmt.setBoolean(8, impresora);
            stmt.setBoolean(9, miniprint);
            stmt.setBoolean(10, laptop);
            stmt.setBoolean(11, escaner);

            // Manejo de fechas
            if (fechaprog != null) {
                stmt.setDate(12, new java.sql.Date(fechaprog.getTime()));
            } else {
                stmt.setNull(12, java.sql.Types.DATE); // Manejo de valor nulo
            }
            stmt.setString(13, tecnicosmt);
            stmt.setString(14, estado);
            stmt.setInt(15, mesId);

            stmt.executeUpdate();

        } catch (SQLException e) {
            System.err.println("Error al insertar nuevo equipo en PLANANUAL: " + e.getMessage());
        }

    }

    // Método auxiliar para obtener un valor de tipo Date de una celda
    private Date getDateCellValue(Cell cell) {
        if (cell != null) {
            switch (cell.getCellType()) {
                case NUMERIC:
                    return new Date(cell.getDateCellValue().getTime()); // Retorna la fecha directamente
                case STRING:
                    try {
                        return Date.valueOf(LocalDate.parse(cell.getStringCellValue().trim())); // Asume formato ISO
                    } catch (Exception e) {
                        System.err.println("No se puede convertir la cadena a fecha: " + cell.getStringCellValue());
                    }
                    break;
                case BLANK:
                    return null; // Devuelve null si la celda está vacía
                default:
                    System.err.println("Tipo de celda inesperado en la fila " + cell.getRowIndex());
                    break;
            }
        }
        return null; // Retorna null si no se puede obtener una fecha
    }

    // Método auxiliar para obtener un valor de tipo String de una celda
    private String getStringCellValue(Cell cell) {
        if (cell != null) {
            switch (cell.getCellType()) {
                case STRING:
                    return cell.getStringCellValue().trim();
                case NUMERIC:
                    return String.valueOf((int) cell.getNumericCellValue()); // Convierte el número a cadena
                default:
                    return ""; // Devuelve cadena vacía si la celda no es de tipo STRING o NUMERIC
            }
        }
        return ""; // Devuelve cadena vacía si la celda es nula
    }

    // Método auxiliar para obtener un valor de tipo boolean de una celda
    private boolean getBooleanCellValue(Cell cell) {
        if (cell != null) {
            switch (cell.getCellType()) {
                case NUMERIC:
                    return cell.getNumericCellValue() != 0; // Considera 0 como false, cualquier otro número como true
                case BOOLEAN:
                    return cell.getBooleanCellValue();
                case STRING:
                    return Boolean.parseBoolean(cell.getStringCellValue().trim()); // Conversión de string a boolean
                default:
                    return false; // Valor por defecto
            }
        }
        return false; // Valor por defecto si la celda es nula
    }

    /* ----------------Actualizar los detalles del del mantenimiento por ID ---------------- */
    public boolean actualizarPlanAnual(int planAnualId, String nombreEquipo) {
        String sql = "UPDATE PLANANUAL SET NOMEQUIPO=? WHERE PLANANUALID=?";
        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(sql)) {
                stmt.setString(1, nombreEquipo);
                stmt.setInt(2, planAnualId);
                return stmt.executeUpdate() > 0;
            } catch (SQLException e) {
                logger.error("Error al actualizar el plan anual: ", e);
                return false;
            }
    }

    public boolean actualizarMantenimiento(int mantenimientoId, int tipoId, String departamentoId, int empleadoId, LocalDate fechaRealizado, String nombreEquipo, String firmausuario, String firmasmt) {
        String sql = "UPDATE MANTENIMIENTOS SET TIPOMANTID=?, DEPARTAMENTOID=?, EMPLEADOID=?, FECHA=?, NOMBREEQUIPO=?, FIRMAUSUARIO=?, FIRMASMT=? WHERE MANTENIMIENTOID=?";
        try (Connection conn = getMysqlConnection();
        PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setInt(1, tipoId);                // tipoId es int
            stmt.setString(2, departamentoId);     // departamentoId es String
            stmt.setInt(3, empleadoId);            // empleadoId es int
            stmt.setDate(4, fechaRealizado != null ? Date.valueOf(fechaRealizado) : null);
            stmt.setString(5, nombreEquipo);
            if (firmausuario != null) {
                stmt.setString(6, firmausuario);
            } else {
                stmt.setNull(6, Types.VARCHAR);
            }
            if (firmasmt != null) {
                stmt.setString(7, firmasmt);
            } else {
                stmt.setNull(7, Types.VARCHAR);
            }
            stmt.setInt(8, mantenimientoId);
            return stmt.executeUpdate() > 0;
        } catch (SQLException e) {
            logger.error("Error al actualizar el mantenimiento: ", e);
            return false;
        }
    }

    /* ----------------Actualizar los detalles del hardaware por ID ---------------- */
    public boolean actualizarHardwareDetalle(HardwareDetalle detalle) {
        String sql = "UPDATE HARDWAREDET SET MODELO=?, NUMSERIE=?, PLACA=? WHERE HARDWAREDETID=?";
        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(sql)) {
                stmt.setString(1, detalle.getModelo());
                stmt.setString(2, detalle.getNumSerie());
                stmt.setString(3, detalle.getPlaca());
                stmt.setInt(4, detalle.getHardwareDetId());
                return stmt.executeUpdate() > 0;
            } catch (SQLException e) {
                logger.error("Error al actualizar el detalle del hardware: ", e);
                return false;
            }
    }

    /* ----------------Actualizar las actualizaciones de seguridad por ID ---------------- */
    public boolean actualizarActualizacionSeg(ActualizacioneSeguridadModel actualizacion) {
        String sql = "UPDATE ACTUALIZACIONESSEG SET OTRASACTUALIZACIONES=? WHERE ACTUALIZACIONSEGID=?";
        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(sql)) {
                stmt.setString(1, actualizacion.getOtrasactualizaciones());
                stmt.setInt(2, actualizacion.getActualizacionsegId());
                return stmt.executeUpdate() > 0;
            } catch (SQLException e) {
                logger.error("Error al actualizar la actualización de seguridad: ", e);
                return false;
            }
    }

    /* ---------------- Insertar en bitacora ---------------- */
    public boolean insertarBitacora(int mantenimientoid, String usuarioid, LocalDate fechora, String motivo) {
        String query = "INSERT INTO BITACORACTUALIZACIONES (MANTENIMIENTOID, USUARIOID, FECHORA, MOTIVO) VALUES (?, ?, ?, ?)";
        try (Connection conn = getMysqlConnection();
            PreparedStatement stmt = conn.prepareStatement(query)) {
                stmt.setInt(1, mantenimientoid);
                stmt.setString(2, usuarioid);
                stmt.setDate(3, fechora != null ? Date.valueOf(fechora) : null);
                stmt.setString(4, motivo);
                return stmt.executeUpdate() > 0;
            } catch (SQLException e) {
                logger.error("Error al insertar en bitacora: ", e);
                return false;
            }
    }

    /* ---------------- Insertar en bitacora de eliminacion de equipos ---------------- */
    public boolean insertarBitacoraEliminacion(int plananualid, String usuarioid, LocalDate fechora, String motivo) {
        String query = "INSERT INTO BITACORAELIMINACIONES (PLANANUALID, USUARIOID, FECHAHORA, MOTIVO) VALUES (?, ?, ?, ?)";
        try (Connection conn = getMysqlConnection();
             PreparedStatement stmt = conn.prepareStatement(query)) {
            stmt.setInt(1, plananualid);
            stmt.setString(2, usuarioid);
            stmt.setDate(3, fechora != null ? Date.valueOf(fechora) : null);
            stmt.setString(4, motivo);
            return stmt.executeUpdate() > 0;
        } catch (SQLException e) {
            logger.error("Error al insertar en bitacora de eliminacion de equipos: ", e);
            return false;
        }
    }

    /* ---------------- Eliminar equipo de PLAN ANUAL ---------------- */
    public void eliminarEquipoPlanAnual(int planAnualId) {
        String sql = "DELETE FROM PLANANUAL WHERE PLANANUALID = ?";
        try (Connection conn = getMysqlConnection();
        PreparedStatement stmt = conn.prepareStatement(sql)) {

            stmt.setInt(1, planAnualId);
            int rowsAffected = stmt.executeUpdate();
            if (rowsAffected > 0) {
                System.out.println(planAnualId + " eliminado correctamente.");
            } else {
                System.out.println("No se encontró el equipo con ID: " + planAnualId);
            }
        } catch (SQLException e) {
            logger.error("Error al eliminar el equipo de PLANANUAL: ", e);
        }
    }



/*************************************** ENCUESTAS ******************************************************************************************************/
    public List<Pregunta> getPreguntas() {
        List<Pregunta> preguntas = new ArrayList<>();
        String query = """
                select p.*
                from PREGUNTAS p
                join ENCUESTAS e on e.ENCUESTAID = p.ENCUESTAID
                where e.ENCUESTAID = 1
                order by p.ORDEN ASC
                """;

        try (Connection conn = getMysqlConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(query)) {

            while (rs.next()) {
                Pregunta pregunta = new Pregunta(
                        rs.getInt("preguntaid"),
                        rs.getInt("encuestaid"),
                        rs.getString("pregunta"),
                        rs.getInt("orden")
                );
                preguntas.add(pregunta);
            }
        } catch (SQLException e) {
            logger.error("Error al obtener las preguntas de la encuesta: ", e);
        }
        return preguntas;
    }

    public void insertRespuestas(int manteniminetoId, List<Respuesta> respuestas, int empleadoid, String comentarios, String token) {

        String insertQuery = """
                insert into RESPUESTAS
                (MANTENIMIENTOID,PREGUNTAID,FECHARESPUESTA,RESPUESTA,EMPLEADOID,COMENTARIOS)
                values
                (?,?,?,?,?,?)
                """;

        String updateQuery = """
                update MANTENIMIENTOS
                set ENCUESTA = 'S'
                where MANTENIMIENTOID = ?
                """;

        String markTokenUsedQuery = """
                update ENCUESTATOKENS
                set USADO = '1' where TOKEN = ?
                """;

        try (Connection conn = getMysqlConnection()) {

            conn.setAutoCommit(false);

            try (PreparedStatement insertStmt = conn.prepareStatement(insertQuery);
            PreparedStatement updateStmt = conn.prepareStatement(updateQuery);
            PreparedStatement tokenStmt = conn.prepareStatement(markTokenUsedQuery)) {

                Timestamp ahora = new Timestamp(System.currentTimeMillis());

                // 1. Insertar las respuestas en el Batch
                for (Respuesta r : respuestas) {
                    insertStmt.setInt(1, manteniminetoId);
                    insertStmt.setInt(2, r.getPreguntaId());
                    insertStmt.setTimestamp(3, ahora);
                    insertStmt.setBoolean(4, r.getRespuesta());
                    insertStmt.setInt(5, empleadoid);
                    insertStmt.setString(6, comentarios);
                    insertStmt.addBatch();
                }

                insertStmt.executeBatch();

                // 2. Marcar mantenimiento como encuestado
                updateStmt.setInt(1, manteniminetoId);
                updateStmt.executeUpdate();

                // 3. Invalidar el token para que no se use de nuevo
                tokenStmt.setString(1, token);
                tokenStmt.executeUpdate();

                conn.commit();

            } catch (SQLException e) {
                conn.rollback();
                throw e;
            }

        } catch (Exception e) {
            throw new RuntimeException("Error al guardar encuesta y procesar el token", e);
        }
    }

    public String crearTokenEncuesta(int mantenimientoid) {
        String token = UUID.randomUUID().toString();
        ZoneId zonaMX = ZoneId.of("America/Mexico_City");
        ZonedDateTime ahora = ZonedDateTime.now(zonaMX);

        ZonedDateTime fechaExp = ahora;
        int diasPorSumar = 3;
        while (diasPorSumar > 0) {
            fechaExp = fechaExp.plusDays(1);
            if (!(fechaExp.getDayOfWeek() == DayOfWeek.SATURDAY ||
                    fechaExp.getDayOfWeek() == DayOfWeek.SUNDAY)) {
                diasPorSumar--;
            }
        }

        Timestamp expira = Timestamp.from(fechaExp.toInstant());
        LocalDate fechaEnvio = ahora.toLocalDate();

        String query = "INSERT INTO ENCUESTATOKENS (TOKEN, MANTENIMIENTOID, FECHAENVIO, FECHAEXPIRACION) VALUES (?, ?, ?, ?)";

        try (Connection conn = getMysqlConnection();
        PreparedStatement stmt = conn.prepareStatement(query)) {

            stmt.setString(1, token);
            stmt.setInt(2, mantenimientoid);
            stmt.setDate(3, java.sql.Date.valueOf(fechaEnvio));
            stmt.setTimestamp(4, expira);
            stmt.executeUpdate();

            return token;

        } catch (SQLException e) {
            logger.error("Error al crear el token de encuesta: ", e);
            throw new RuntimeException("Ya existe una encuesta para este mantenimiento o error en DB", e);
        }
    }

    public Integer validarTokenYObtenerId(String token) {
        String query = "SELECT MANTENIMIENTOID FROM ENCUESTATOKENS " +
                        "WHERE TOKEN = ? AND FECHAEXPIRACION > NOW() AND USADO = FALSE";

        try (Connection conn = getMysqlConnection();
        PreparedStatement stmt = conn.prepareStatement(query)) {
            stmt.setString(1, token);
            ResultSet rs = stmt.executeQuery();
            if (rs.next()) {
                return rs.getInt("MANTENIMIENTOID");
            }
        } catch (SQLException e) {
            logger.error("Error al validar el token de encuesta: ", e);
        }
        return null;
    }

    public List<ConteoEncuestas> getTotalEncuestas(Integer mesId, Integer anio) {
        List<ConteoEncuestas> totalEncuestas = new ArrayList<>();
        String query = "{call sp_reporte_encuestas(?, ?)}";

        try (Connection conn = getMysqlConnection();
             CallableStatement cstmt = conn.prepareCall(query)) {

            if (mesId != null) {
                cstmt.setInt(1, mesId);
            } else {
                cstmt.setNull(1, Types.INTEGER);
            }

            if (anio != null) {
                cstmt.setInt(2, anio);
            } else {
                cstmt.setNull(2, Types.INTEGER);
            }

            try (ResultSet rs = cstmt.executeQuery()) {
                while (rs.next()) {
                    ConteoEncuestas conteo = new ConteoEncuestas(
                            rs.getInt("TOTAL_ENVIADAS"),
                            rs.getInt("TOTAL_RESPONDIDAS"),
                            rs.getDouble("PORCENTAJE_TOTAL")
                    );
                    totalEncuestas.add(conteo);
                }
            }
        } catch (SQLException e) {
            logger.error("Error al obtener el total de encuestas: ", e);
        }
        return totalEncuestas;
    }

    public List<ConteoRespuestas> getTotalRespuestas(Integer mesId, Integer anio) {
        List<ConteoRespuestas> totalRespuestas = new ArrayList<>();
        String query = "{call sp_reporte_respuestas(?, ?)}";

        try (Connection conn = getMysqlConnection();
             CallableStatement cstmt = conn.prepareCall(query)) {

            if (mesId != null) {
                cstmt.setInt(1, mesId);
            } else {
                cstmt.setNull(1, Types.INTEGER);
            }

            if (anio != null) {
                cstmt.setInt(2, anio);
            } else {
                cstmt.setNull(2, Types.INTEGER);
            }

            try (ResultSet rs = cstmt.executeQuery()) {
                while (rs.next()) {
                    ConteoRespuestas conteo = new ConteoRespuestas(
                            rs.getInt("PREGUNTAID"),
                            rs.getString("PREGUNTA"),
                            rs.getInt("TOTALREGISTROS"),
                            rs.getInt("TOTALSI"),
                            rs.getInt("TOTALNO"),
                            rs.getDouble("PORCENTAJE")
                    );
                    totalRespuestas.add(conteo);
                }
            }
        } catch (SQLException e) {
            logger.error("Error al obtener el total de respuestas: ", e);
        }
        return totalRespuestas;
    }
    /***************************************************************************************************************************************/
}
