<?php







defined('BASEPATH') or exit('No direct script access allowed');







/**



 * Acceso al sistema para el participante.



 *



 * @author Jaime Bravo <jbravo@cyberiatech.com.co>



 * @copyright (c) 2016, CyberiaTech SAS



 */



class Acceso extends MX_Controller



{







    /**



     * Path js.



     * @var type



     */



    public $path_js;







    /**



     *



     * @var type



     */



    private $_configuracion;


    // reCAPTCHA v2 (checkbox)
    private $RECAPTCHA_SITE   = '6Lf4i7IrAAAAAJPtB8_Fd5T__qJPSG41zhPP58d_';
    private $RECAPTCHA_SECRET = '6Lf4i7IrAAAAAG9Fn3ud9w39CNmlxGEszRh3lwQJ';





    //------------------------------------------------------------------------------







    /**



     * Método constructor.



     */



    public function __construct()



    {







        parent::__construct();



        $this->load->model('Access');
        $this->ini_desencriptado();


        $this->load->model([
            'participantes/Participante',



            'configuracion/Config',
            'instancias/Instancia',
            'log_ingresos/Log_ingreso',



            'Log_recordar_password',
            'ingresos_salidas/Ingresos_salida'
        ]);



        //Para que funcione el callback en la libreria de validación.



        $this->form_validation->CI = &$this;



        $this->load->helper('security');



        $this->path_js = 'acceso/scripts_dev.js';







        //Config del sistema



        $this->_configuracion = $this->Config->get_row();







        //Si no esta definida la configuración.



        if (!$this->_configuracion) {



            $data_view['message'] = 'No se ha definido la configuración del sistema. Contacte al administrador.';



            $this->load->view('errors/error_start_sistema', $data_view);



            return false;
        }
    }







    //------------------------------------------------------------------------------



    /**



     *  Valida si el participante esta registrado.



     *



     * @return boolean



     */



    public function check_registro_participante()



    {



        $participante = ltrim($this->input->post('NUM_IDETER'), '0');


        $this->db->where('FEC_REGIST IS NOT NULL', null, false);
        //  $this->db->where('FEC_REGIST !=', 'NULL');



        $consulta = $this->Participante->get($participante);



        if (!$consulta) {



            $this->form_validation->set_message('check_registro_participante', 'El participante aun no está registrado.');



            return false;
        } else {



            return true;
        }
    }







    public function valida_estado_participante()



    {



        $participante = ltrim($this->input->post('NUM_IDETER'), '0');



        $this->db->where('BOL_ACTIVO', 0);



        $this->db->where('IS_DELETE', 1);



        $consulta = $this->Participante->get($participante);



        if ($consulta) {



            $this->form_validation->set_message('valida_estado_participante', 'Los datos del participante no están habilitados para el proceso.');



            return false;
        } else {



            return true;
        }
    }







    //------------------------------------------------------------------------------



    /**



     * Valida si el participante existe;



     * @return boolean



     */



    public function exist_participante()



    {



        $participante = ltrim($this->input->post('NUM_IDETER'), '0');



        $consulta     = $this->Participante->get($participante);



        if (!$consulta) {



            $this->form_validation->set_message('exist_participante', $this->get_texto_sistema('TEX_ERUSNO')->TEX_LABEL);



            return false;
        } else {



            return true;
        }
    }











    //------------------------------------------------------------------------------



    /**



     * Valida si el participante esta inactivo;



     * @return boolean



     */



    public function participante_inactivo()



    {



        $participante = $this->input->post('NUM_IDETER');



        $consulta     = $this->Participante->get($participante);



        if (!isset($consulta->BOL_ACTIVO)) {



            $this->form_validation->set_message('participante_inactivo', $this->get_texto_sistema('TEX_PARINACT')->TEX_LABEL);



            return false;
        } else {



            return true;
        }
    }







    //------------------------------------------------------------------------------



    /**



     * Valida si el participante tiene una sesión abierta.



     * @return boolean



     */



    public function session_participante()



    {



        /*  $participante = ltrim($this->input->post('NUM_IDETER'), '0');



        $this->db->where('BOL_INISES', 1);



        $consulta = $this->Participante->get($participante);



        if ($consulta) {



            $this->form_validation->set_message('session_participante', 'Ya hay una sesión abierta');



            return false;



        } else {



            return true;



        }*/

        return true;
    }







    //------------------------------------------------------------------------------



    /**



     * Valida si ha votado previamente



     *



     * @return boolean



     */



    public function valida_votacion_previa()



    {





        $participante = ltrim($this->input->post('NUM_IDETER'), '0');



        $instancia_activa =  $this->Instancia->get_by(['BOL_ACTIVO' => 1, 'IS_DELETE' => 0]);



        $instancias_activas =  $this->Instancia->all();



        if (!$instancia_activa) {



            $this->form_validation->set_message('valida_votacion_previa', 'No hay una instancia activa en el momento');



            return false;
        }



        $acumulador = array();

        foreach ($instancias_activas as $intans) {

            $validacion_voto_previo = $this->Participante->get_exits_voto($intans->ID_INSTAN, $participante_id);

            if (!$validacion_voto_previo) {

                $valor = array($intans->ID_INSTAN);

                $acumulador = array_merge($acumulador, $valor);
            }
        }

        if (empty(current($acumulador))) {



            $data_view['message'] = $this->get_texto_sistema('TEX_ISVOTO')->TEX_LABEL;



            $this->load->view('login', $data_view);



            return false;
        } else {



            return true;
        }

        /*

        $consulta     = $this->Participante->get_exits_voto($instancia_activa->ID_INSTAN, $participante);



        if ($consulta) {



            $this->form_validation->set_message('valida_votacion_previa', $this->get_texto_sistema('TEX_ISVOTO')->TEX_LABEL);



            return false;



        } else {



            return true;



        }

*/
    }







    //------------------------------------------------------------------------------







    /**



     * Login del participante.



     */



    public function login()

    {

        if (!$this->session->userdata('NUM_IDETER')) {



            //Datos de la primera instancia activa.

            $instancia = $this->Instancia->get_instancia_by_id();



            if ($instancia) {

                $valida_fecha = $this->valida_fecha_vigencia_instancia($instancia);



                //Si la validación de fechas no se cumple.

                if (!$valida_fecha) {

                    return false;
                }
            }



            $data_view['titulo'] = 'Ingreso a votación';

            $data_view['images'] = [

                'uploads/backgrounds/tech1.jpg',

                'uploads/backgrounds/tech2.jpg',

                'uploads/backgrounds/tech3.jpg',

                'uploads/backgrounds/tech4.jpg',

                'uploads/backgrounds/tech1.jpg',

                'uploads/backgrounds/tech2.jpg',

                'uploads/backgrounds/tech3.jpg',

                'uploads/backgrounds/tech4.jpg',

            ];

            $data_view['load_js'] = $this->path_js;

            $data_view['tipo_acceso'] = $this->_configuracion->NUM_VALING;

            $data_view['activar_rec_password'] = (bool)$this->_configuracion->BOL_ACTRECCON;

            $data_view['activar_ayuda_wa'] = (bool)$this->_configuracion->BOL_ACTBTNWA;

            $data_view['mensaje_login'] = $this->get_texto_sistema('TEX_LOGIN')->TEX_LABEL;

            $data_view['logo'] = $this->Access->get_logo_empresa();

            $data_view['nombre_empresa'] = $this->Access->get_nom_empresa()->TEX_NOMEMP;

            $data_view['celular_mesa_ayuda'] =$this->Access->get_empresa_info()->TEX_CELEMP;
            // === Bloque de vigencia para el login (contador) ===
            $data_view['vigencia_mode'] = (int)($this->_configuracion->NUM_VIGENCIA_MODE ?? 0);   // 0=Off,1=Desde-Hasta+contador,2=Hasta+contador,3=Solo contador
            $data_view['vigencia_font'] = (int)($this->_configuracion->NUM_VIGENCIA_FONT ?? 18);  // tamaño de fuente (px)

            // Reutilizamos $instancia que ya cargaste arriba
            $data_view['vigencia_start_iso'] = null;
            $data_view['vigencia_end_iso']   = null;

            if ($instancia) {
                $ini = $instancia->FEC_INIUSO ?? null;
                $fin = $instancia->FEC_FINUSO ?? null;

                if ($ini && $ini !== '0000-00-00 00:00:00') {
                    $data_view['vigencia_start_iso'] = date('c', strtotime($ini)); // ISO 8601
                }
                if ($fin && $fin !== '0000-00-00 00:00:00') {
                    $data_view['vigencia_end_iso']   = date('c', strtotime($fin));
                }
            }
            // === fin bloque de vigencia ===
            $data_view['captcha_enabled'] = (bool)$this->_configuracion->BOL_CAPTCHA_LOGIN;
            $data_view['captcha_sitekey'] = $this->RECAPTCHA_SITE;




            if ($this->input->post()) {



                $participante_id = ltrim($this->input->post('NUM_IDETER'), '0');



                // Validacion si hay instancias activas. 

                $instancias_activas = $this->Instancia->all();



                /* if(!$instancias_activas) {

                    $data_view['message'] = $this->get_texto_sistema('TEX_INSTA_INACTIVA')->TEX_LABEL;

                    $this->load->view('login', $data_view);

                    return false;

                }*/



                //Validacion si el participante ya ha votado.

                $acumulador = array();

                foreach ($instancias_activas as $intans) {

                    $validacion_voto_previo = $this->Participante->get_exits_voto($intans->ID_INSTAN, $participante_id);

                    if (!$validacion_voto_previo) {

                        $valor = array($intans->ID_INSTAN);

                        $acumulador = array_merge($acumulador, $valor);
                    }
                }

                if (empty(current($acumulador))) {

                    $data_view['message'] = $this->get_texto_sistema('TEX_ISVOTO')->TEX_LABEL;

                    $this->load->view('login', $data_view);

                    return false;
                }



                //Validación previa comentada

                /* $validacion_voto_previo = $this->Participante->get_exits_voto($instancia->ID_INSTAN, $participante_id);

                if ($validacion_voto_previo) {

                    $data_view['message'] = $this->get_texto_sistema('TEX_ISVOTO')->TEX_LABEL;

                    $this->load->view('login', $data_view);

                    return false;

                }*/



                //Se valida que sea con registro previo.

                if ($this->_configuracion->BOL_REGIST) {

                    $this->db->where('FEC_REGIST IS NOT NULL', null, false);

                    $validacion_registro = $this->Participante->get($participante_id);

                    if (!$validacion_registro) {

                        $data_view['message'] = $this->get_texto_sistema('PARTI_NO_REGIS')->TEX_LABEL;

                        $this->load->view('login', $data_view);

                        return false;
                    }



                    //Validacion si el participante esta fuera del auditorio.

                    $validacion_fuera_auditorio = $this->Ingresos_salida->valida_participante_fuera_auditorio($participante_id);

                    if ($validacion_fuera_auditorio) {

                        $data_view['message'] = $this->get_texto_sistema('TEX_PART_FUERA_AUDI')->TEX_LABEL;

                        $this->load->view('login', $data_view);

                        return false;
                    }
                }



                $data_view['message'] = validation_errors();

                $tipo_acceso = $this->input->post('TIPO_ACCESO');



                $this->form_validation->set_rules('NUM_IDETER', 'Identificación', 'trim|required|integer|callback_participante_inactivo|callback_valida_estado_participante|callback_exist_participante|callback_valida_votacion_previa|callback_session_participante');



                if ($this->_configuracion->BOL_REGIST) {

                    $this->form_validation->set_rules('NUM_IDETER', 'Identificación', 'callback_participante_inactivo|callback_exist_participante|callback_session_participante|callback_check_registro_participante');
                }



                if ($tipo_acceso === 'W') {

                    $this->form_validation->set_rules('TEX_CLAVE', 'Contraseña', 'required|min_length[4]');
                }

                if ($tipo_acceso === 'P') {

                    $this->form_validation->set_rules('TEX_CLAVE', 'Contraseña', 'required|min_length[4]');

                    $this->form_validation->set_rules('NUM_TELCEL', 'Número de celular', 'trim|required|integer');
                }

                if ($tipo_acceso === 'CP') {

                    $this->form_validation->set_rules('NUM_PINGEN', 'PIN', 'trim|required|integer');
                }

                // Si el captcha está activo, lo hacemos obligatorio
                if ((int)$this->_configuracion->BOL_CAPTCHA_LOGIN === 1) {
                    $this->form_validation->set_rules('g-recaptcha-response', 'Captcha', 'callback__valid_recaptcha');
                }


                if ($this->form_validation->run() == false) {

                    $data_view['message'] = validation_errors();

                    $this->load->view('login', $data_view);

                    return false;
                } else {

                    $valida_ip_agencia = $this->Access->get_ip_agencia_participante(xss_clean($this->input->post('NUM_IDETER')));

                    $valida_ip_agencia = (isset($valida_ip_agencia->TEX_IPORIG)) ? $valida_ip_agencia->TEX_IPORIG : '0';



                    if ($valida_ip_agencia !== '' || !empty($valida_ip_agencia)) {

                        if ($valida_ip_agencia !== '0') {

                            if ($valida_ip_agencia != $this->get_client_ip_server()) {

                                $data_view['message'] = $this->get_texto_sistema('TEX_VALIPORIG')->TEX_LABEL;

                                $this->load->view('login', $data_view);

                                return false;
                            }
                        }
                    }



                    //Inicio de session más común. user - pass

                    if ($tipo_acceso === 'W') {

                        $acceso = xss_clean($this->input->post('NUM_IDETER'));

                        $password = sha1($this->input->post('TEX_CLAVE'));

                        $usuario_existe = $this->Participante->get($acceso);

                        $data_view['iden'] = $acceso;

                        $data_view['pass'] = $password;



                        if (!$usuario_existe) {

                            $data_view['message'] = $this->get_texto_sistema('TEX_ERUSNO')->TEX_LABEL;

                            $this->load->view('login', $data_view);

                            return false;
                        }



                        // **Cambios nuevos: Verificación de bloqueos por intentos fallidos**

                        $tiempo_bloqueo = $this->_configuracion->NUM_BLOQ_TEMPO; // Tiempo de bloqueo desde la configuración

                        $this->db->select('FEC_BLOQLOGIN');

                        $this->db->where('NUM_IDETER', $acceso);

                        $this->db->order_by('FEC_BLOQLOGIN', 'DESC');

                        $ultimo_bloqueo = $this->db->get('evi05particlogeo')->row();



                        // Consultar el valor de BOL_BLOQUEADO en la tabla evi05partic

                        $this->db->select('BOL_BLOQUEADO');

                        $this->db->where('NUM_IDETER', $acceso);

                        $estado_bloqueo = $this->db->get('evi05partic')->row();



                        if ($ultimo_bloqueo) {

                            // Validar si BOL_BLOQUEADO está en 0 (desbloqueado manualmente)

                            if ($estado_bloqueo && $estado_bloqueo->BOL_BLOQUEADO == 0) {

                                // Permitir ingreso sin alertas ni lógica de bloqueos

                                log_message('info', "Usuario con ID $acceso desbloqueado manualmente. Permitiendo ingreso.");
                            } else {

                                $fecha_desbloqueo = strtotime($ultimo_bloqueo->FEC_BLOQLOGIN) + ($tiempo_bloqueo * 60);



                                // **Desbloqueo automático si el tiempo ha expirado**

                                if (time() >= $fecha_desbloqueo) {

                                    $this->Participante->update($acceso, ['NUM_INTENLOGIN' => 0, 'BOL_BLOQUEADO' => 0]);



                                    $data_observacion = [

                                        'NUM_IDETER' => $acceso,

                                        'FEC_BLOQLOGIN' => date('Y-m-d H:i:s'),

                                        'TEX_OBSERVACION' => 'Desbloqueo automático.'

                                    ];

                                    $this->db->insert('evi05particlogeo', $data_observacion);



                                    log_message('info', "Usuario con ID $acceso desbloqueado automáticamente.");
                                } else {

                                    // **Si el tiempo no ha expirado y no está desbloqueado manualmente**

                                    $tiempo_restante = ceil(($fecha_desbloqueo - time()) / 60); // Minutos restantes

                                    $data_view['message'] = "Su cuenta está bloqueada. Inténtelo de nuevo en $tiempo_restante minutos.";

                                    $this->load->view('login', $data_view);

                                    return false;
                                }
                            }
                        }



                        // **Código original de intentos de login comentado**

                        /* $intentos_login = (int)$usuario_existe->NUM_INTENLOGIN;

                        if (!$intentos_login) {

                            $intentos_login = 1;

                        }

                        if ($intentos_login == $this->_configuracion->NUM_INLOGIN) {

                            $this->Participante->update_participante_bloqueo($acceso);

                            $data_view['message'] = 'Usuario bloqueado. Ha alcanzado el número máximo de intentos. Contacte al administrador.';

                            $this->load->view('login', $data_view);

                            return false;

                        }*/



                        // Nuevo manejo de bloqueos

                        if ((int)$usuario_existe->NUM_INTENLOGIN == $this->_configuracion->NUM_INLOGIN && $estado_bloqueo->BOL_BLOQUEADO == 0) {

                            $this->Participante->update_participante_bloqueo($acceso);



                            // Insertar registro en evi05particlogeo

                            $data_bloqueo = [

                                'NUM_IDETER' => $acceso,

                                'FEC_BLOQLOGIN' => date('Y-m-d H:i:s'),

                                'TEX_OBSERVACION' => 'Bloqueo automático por intentos fallidos.'

                            ];

                            $this->db->insert('evi05particlogeo', $data_bloqueo);



                            $data_view['message'] = "Usuario bloqueado. Ha alcanzado el número máximo de intentos.";

                            if ($tiempo_bloqueo > 0) {

                                $data_view['message'] .= " Inténtelo de nuevo en $tiempo_bloqueo minutos.";
                            } else {

                                $data_view['message'] .= " Contacte al administrador.";
                            }

                            $this->load->view('login', $data_view);

                            return false;
                        }



                        $ini_session = $this->_inicio_session($acceso, $password);



                        if (!$ini_session) {

                            $this->Participante->update_intentos_login($acceso);

                            $intentos_bd = $this->Participante->get($acceso);

                            $intentos_actualizados = (int)$intentos_bd->NUM_INTENLOGIN; // Método para consultar el valor actualizado

                            $intentos_login_restantes = $this->_configuracion->NUM_INLOGIN - $intentos_actualizados;

                            // $intentos_login_restantes = $this->_configuracion->NUM_INLOGIN - $intentos_login;

                            $data_view['message'] = $this->get_texto_sistema('TEX_ERCLNO')->TEX_LABEL;

                            $data_view['message2'] = 'Le quedan: ' . $intentos_login_restantes . ' intentos de login';

                            $this->load->view('login', $data_view);



                            return false;
                        }
                    }





                    if ($tipo_acceso === 'I') {



                        $acceso = xss_clean($this->input->post('NUM_IDETER'));



                        $this->_inicio_session($acceso);
                    }



                    //Pin



                    if ($tipo_acceso === 'P') {



                        $acceso   = xss_clean($this->input->post('NUM_IDETER'));



                        $password = sha1($this->input->post('TEX_CLAVE'));



                        $celular  = xss_clean($this->input->post('NUM_TELCEL'));



                        unset($_POST['TEX_CLAVE']);



                        unset($_POST['TIPO_ACCESO']);



                        unset($_POST['submit']);



                        $this->db->where('TEX_CLAVE', $password);



                        $validacion_ingreso    = $this->Participante->get($acceso);



                        $valida_unico_telefono = $this->Access->valida_unico_celular($celular);







                        if ($valida_unico_telefono) {



                            $data_view['message'] = 'Este número de celular ya ha sido usado por otro participante.';



                            $this->load->view('login', $data_view);



                            return false;
                        }



                        //Si los datos no corresponden



                        if (!$validacion_ingreso) {



                            $data_view['message'] = 'Identificación o celular incorrecto, el acceso está desactivado o hay otra sessión abierta';



                            $this->load->view('login', $data_view);



                            return false;
                        }



                        //Si genera Pin



                        if ($this->_configuracion->BOL_VALPIN) {



                            // Crea log
                      
                            $pin = $this->get_pin_sms();



                            if ($this->Access->insert_log_ingreso($_POST, $pin)) {



                                $data_view['message']        = ['success' => 'Se envió el PIN al teléfono proporcionado'];



                                $data_view['identificacion'] = $acceso;



                                $data_view['celular']        = $celular;



                                $data_view['tipo_acceso']    = 'CP';



                                //Envío de mensaje de Texto.



                                if ($this->_configuracion->BOL_VALSMS) {



                                    $this->_send_mensaje_texto($celular, $pin);
                                } else {



                                    $data_view['message'] = ['success' => 'El PIN para pruebas es: ' . $pin];
                                }







                                $this->load->view('confirma_pin', $data_view);



                                return false;
                            } else {



                                $data_view['message'] = ['error' => 'Error generando el PIN'];



                                $this->load->view('confirma_pin', $data_view);



                                return false;
                            }
                        } else {



                            $this->db->where('TEX_CLAVE', $password);



                            $validacion_password = $this->Participante->get($acceso);



                            $ingreso_pin_directo = $this->Access->valida_existencia_participante($acceso, $celular);







                            if (!$validacion_password) {



                                $data_view['message'] = 'Password no corresponde';



                                $this->load->view('login', $data_view);



                                return false;
                            }







                            if (!$ingreso_pin_directo) {



                                $data_view['message'] = 'Usuario sin pin.';



                                $this->load->view('login', $data_view);



                                return false;
                            }







                            $this->_inicio_session($acceso, '', true);



                            return false;
                        }



                        return false;
                    }

                  if ($tipo_acceso === 'CP') {

    $acceso  = xss_clean($this->input->post('NUM_IDETER'));
    $celular = xss_clean($this->input->post('NUM_TELCEL'));
    $pin     = xss_clean($this->input->post('NUM_PINGEN'));

    // 🔹 Obtener la clave fija desencriptada (si existe)
    $clave_fija_plain = '';
    if (!empty($this->_configuracion->TEX_PASS_FIJA_DEF)) {
        $clave_fija_plain = $this->desencriptar_texto($this->_configuracion->TEX_PASS_FIJA_DEF);
     }

    // 🔹 Valida la existencia del PIN normal
    $valida_pin = $this->Access->valida_pin_ingreso($acceso, $celular, $pin);

    // 🔹 Si el PIN no coincide con lo registrado...
    if (!$valida_pin->FEC_CREACION) {

        // ...entonces verificamos si el usuario ingresó la clave fija
        if ($clave_fija_plain !== '' && $pin === $clave_fija_plain) {
            // ✅ Si coincide con la clave fija, permitimos el ingreso directamente
            $this->_inicio_session($acceso, '', true);
            return false;
        }

        // ❌ Si tampoco coincide, se muestra el mensaje de error habitual
        $data_view['identificacion'] = $acceso;
        $data_view['celular']        = $celular;
        $data_view['tipo_acceso']    = 'CP';
        $data_view['message']        = ['error' => 'PIN proporcionado es incorrecto'];
        $this->load->view('confirma_pin', $data_view);
        return false;
    }

    // 🔹 Validar el tiempo de caducidad solo si el PIN fue encontrado
    $valida_caducidad = $this->valida_dif_minutos_pin($valida_pin->FEC_CREACION, 10);

    if (!$valida_caducidad) {
        $data_view['tipo_acceso'] = 'P';
        $data_view['message']     = 'El tiempo del PIN ha caducado, debe regenerarlo';
        $this->load->view('login', $data_view);
        return false;
    }

    // ✅ Si el PIN normal es válido o no ha caducado, inicia sesión como siempre
    $this->_inicio_session($acceso, '', true);
}




                    // **Fin de cambios**

                }
            } else {

                $this->load->view('login', $data_view);
            }
        } else {

            if ($this->_configuracion->BOL_VALLIS) {

                redirect('votacion/Votacion_listas');
            } else {



                redirect('votacion');
            }
        }
    }







    public function get_client_ip_server()
    {



        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {



            $ip = $_SERVER['HTTP_CLIENT_IP'];
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {



            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else {



            $ip = $_SERVER['REMOTE_ADDR'];
        }



        return $ip;
    }



    public function _valid_recaptcha($token)
    {
        if ((int)$this->_configuracion->BOL_CAPTCHA_LOGIN !== 1) {
            return true; // apagado: no valida
        }

        $token = trim((string)$token);
        if ($token === '') {
            $this->form_validation->set_message('_valid_recaptcha', 'Por favor confirme el CAPTCHA.');
            return false;
        }

        $url  = 'https://www.google.com/recaptcha/api/siteverify';
        $data = http_build_query([
            'secret'   => $this->RECAPTCHA_SECRET,
            'response' => $token,
            'remoteip' => $this->get_client_ip_server(),
        ]);

        // cURL
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST           => true,
            CURLOPT_POSTFIELDS     => $data,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => 10,
        ]);
        $res = curl_exec($ch);
        $err = curl_error($ch);
        curl_close($ch);

        if ($res === false) {
            log_message('error', 'reCAPTCHA error: ' . $err);
            $this->form_validation->set_message('_valid_recaptcha', 'No se pudo validar el CAPTCHA. Intente de nuevo.');
            return false;
        }

        $json = json_decode($res, true);
        if (!is_array($json) || empty($json['success'])) {
            $this->form_validation->set_message('_valid_recaptcha', 'Validación de CAPTCHA inválida.');
            return false;
        }

        return true;
    }


    //------------------------------------------------------------------------------







    /**



     *  Inicio de sesión del participante.



     *



     * @param type $acceso



     * @param type $password



     * @param type $is_pin



     * @return boolean



     */



    private function _inicio_session($acceso, $password = null, $is_pin = null)



    {



        $login_status = $this->Access->login_participante($acceso, $password);



        if (!$login_status) {



            return false;
        } else {



            $start_session = $this->_start_session_usuario(
                $login_status->NUM_IDETER,
                $login_status->TEX_NOMPAR,
                $login_status->TEX_APEPAR,
                $login_status->COD_CIUDAD,



                $login_status->COD_AGENCIA,
                $login_status->TEX_MAIL,
                $login_status->NUM_PESO,
                $login_status->TEX_NOMAGE,
                $login_status->FEC_INISES,
                $is_pin
            );







            if ($start_session) {

                if ($this->_configuracion->NUM_TEMPO) {



                    $tiempo_votacion = $this->timer_votacion();



                    $this->load->helper('cookie');



                    delete_cookie('tm');



                    setcookie('tm', $tiempo_votacion);
                }







                $this->_update_inisession_participante($is_pin);







                if ($this->_configuracion->BOL_VALLIS) {



                    redirect('votacion/Votacion_listas');
                } else {



                    redirect('votacion');
                }
            } else {





                $data_view['message'] = 'Error al iniciar la session';



                $this->load->view('login', $data_view);
            }
        }
    }







    public function timer_votacion()



    {



        $tiempo_restante = $this->_configuracion->NUM_TEMPO;



        if (!$tiempo_restante) {



            return 0;
        }



        $tiempo_en_seg = $tiempo_restante * 60;



        return $tiempo_en_seg;
    }







    //------------------------------------------------------------------------------







    /**



     * Actualiza el estado de inicio de sessión del participante.



     *



     * @param type $valor



     * @param type $status



     */



    private function _update_inisession_participante($is_pin = null)



    {



        $session_id = $this->session->userdata('session_id');



        if ($this->session->userdata('logged_in')) {



            $this->Participante->edit($this->session->userdata('NUM_IDETER'), ['FEC_INISES' => date('Y-m-d H:i:s'), 'BOL_INISES' => 1, 'NUM_INTENLOGIN' => 0, 'BOL_SESIONID' => $session_id]);



            if ($is_pin) {



                $this->Log_ingreso->edit($valor, ['FEC_INISES' => $this->get_fecha_hora_hoy()]);
            }
        }
    }



    //------------------------------------------------------------------------------







    /**



     *  Inicio de sessión del participante.



     *



     * @param type $identificacion



     * @param type $nombre



     * @param type $apellido



     * @param type $ciudad



     * @param type $agencia



     * @param type $email



     * @return boolean



     */



    private function _start_session_usuario($identificacion, $nombre, $apellido, $ciudad, $agencia, $email, $peso_voto, $nombre_agencia, $fecha, $is_pin = null)



    {

        session_start();



        $nombre_campo_agencia = $this->_configuracion->TEX_NOMSEG;







        $instancias_activas = $this->Instancia->all();



        $arr_instancias_activas = [];



        foreach ($instancias_activas as $key => $instancia) {



            $arr_instancias_activas[] = $instancia->ID_INSTAN;
        }







        $user_data = array(



            'NUM_IDETER'  => $identificacion,



            'TEX_NOMPAR'  => $nombre,



            'TEX_APEPAR'  => $apellido,



            'COD_CIUDAD'  => (int) $ciudad,



            'COD_AGENCIA' => (int) $agencia,



            'TEX_NOMAGE'  => $nombre_agencia,



            'TEX_NOMSEG'  => $nombre_campo_agencia,



            'TEX_MAIL'    => $email,



            'PESO_VOTO'    => $peso_voto,



            'BOL_INISES'  => (int) 1,



            'logged_in'   => true,



            'is_pin'      => $is_pin,



            'instancias_activas'      => $arr_instancias_activas,



            'FEC_INISES'      => $fecha,

            'session_id'      => session_id(),



        );







        $this->session->set_userdata($user_data);



        return true;
    }







    //------------------------------------------------------------------------------







    /**



     * Para salir de la aplicación.



     */



    public function logout($salida_segura = '')



    {



        $this->load->helper('cookie');







        if (!$salida_segura) {



            if ($this->session->userdata('is_pin')) {



                $this->Log_ingreso->edit($this->session->userdata('NUM_IDETER'), ['FEC_FINSES' => $this->get_fecha_hora_hoy(), 'BOL_USADO' => 1]);
            }
        }







        if ($salida_segura) {



            $this->Participante->edit($this->session->userdata('NUM_IDETER'), ['BOL_INISES' => 0]);
        }







        if ((bool)get_cookie('punto_votacion')) {



            $this->session->sess_destroy();



            redirect('/moduloVotacion');
        }



        $this->session->sess_destroy();



        redirect('/');
    }







    //------------------------------------------------------------------------------







    /**



     * Calcula difernecia en minutos a partir de una fecha tipo DATETIME.



     *



     * @param type $fecha_generacion



     * @return type



     */



    public function calcula_diferencia_minutos($fecha_generacion)



    {



        $to_time   = strtotime(date('Y-m-d H:i:s'));



        $from_time = strtotime($fecha_generacion);



        return round(abs($to_time - $from_time) / 60, 2);
    }







    //------------------------------------------------------------------------------







    /**



     * Si el tiempo inicial es mayor al tiempo del parámetro retorna falso.



     *



     * @param type $fecha_generacion



     * @param type $minutos



     * @return boolean



     */



    public function valida_dif_minutos_pin($fecha_generacion, $minutos)



    {



        $tiempo_generado = $this->calcula_diferencia_minutos($fecha_generacion);



        if ($tiempo_generado > (float) $minutos) {



            return false;
        }



        return true;
    }




/**
 * Devuelve la contraseña que se debe enviar al participante según la config:
 * - Si BOL_CONGELA_CLAVE=1:
 *   - Si el participante ya tiene TEX_PASS_FIJA -> la desencripta y la retorna (no cambia nada).
 *   - Si NO tiene TEX_PASS_FIJA -> toma la de config (TEX_PASS_FIJA_DEF) o genera una,
 *     la guarda como fija (TEX_PASS_FIJA encriptada + TEX_CLAVE=sha1) y la retorna.
 * - Si BOL_CONGELA_CLAVE=0 -> genera una nueva, actualiza TEX_CLAVE=sha1 y la retorna.
 *
 * Requiere que evi05partic tenga el campo TEX_PASS_FIJA para guardar la fija (encriptada).
 */
private function _get_password_para_recordar($participante, &$error = null)
{
    $error    = null;
    $congelar = ((int)$this->_configuracion->BOL_CONGELA_CLAVE === 1);

    if ($congelar) {
        // NUNCA aleatoria aquí:
        // 1) Si ya tiene fija -> usarla
        if (!empty($participante->TEX_CLAVE_FIJA)) {
            return $this->desencriptar_texto($participante->TEX_CLAVE_FIJA);
        }

        // 2) Si no tiene fija -> debe existir fija por defecto en Config
        if (!empty($this->_configuracion->TEX_PASS_FIJA_DEF)) {
            $plain = $this->desencriptar_texto($this->_configuracion->TEX_PASS_FIJA_DEF);

          

            return $plain;
        }

        // 3) Congelado pero sin fija por defecto -> error explícito
        $error = 'Falta configurar la contraseña fija por defecto en Configuración.';
        return null;
    }

    // === MODO DINÁMICO (congelar = 0) ===
    $plain = $this->_generateRandomString();
    
    return $plain;
}





    //------------------------------------------------------------------------------



    /**



     * Valida la vigencia de la instancia con referencia a la fecha de inicio y



     * la fecha final.



     *



     * @param type $instancia



     */



    public function valida_fecha_vigencia_instancia($instancia)



    {



        setlocale(LC_ALL, "es_CO");



        $fecha_ini_instancia = $instancia->FEC_INIUSO;
$formatter = new IntlDateFormatter(
    'es_ES',
    IntlDateFormatter::FULL,
    IntlDateFormatter::NONE,
    'America/Bogota',
    IntlDateFormatter::GREGORIAN,
    "HH:mm:ss a 'del' EEEE dd 'de' MMMM 'de' yyyy"
);

$fecha_ini_instancia_format = $formatter->format(strtotime($instancia->FEC_INIUSO));


      //  $fecha_ini_instancia_format = iconv('ISO-8859-2', 'UTF-8', strftime("%H:%M:%S %p del %A %d de %B de %Y", strtotime($instancia->FEC_INIUSO)));




$fecha_fin_instancia_format = $formatter->format(strtotime($instancia->FEC_FINUSO));

       // $fecha_fin_instancia_format = iconv('ISO-8859-2', 'UTF-8', strftime(" %H:%M:%S %p del %A %d de %B de %Y ", strtotime($instancia->FEC_FINUSO)));



        $fecha_fin_instancia = $instancia->FEC_FINUSO;



        $fecha_hoy           = date('Y-m-d H:i:s');



        $data_view['logo'] = $this->Access->get_logo_empresa();







        $mensaje_cierre_fechas = '.<br><br>	 Vigencia del proceso desde: <b style="font-weight:600">' . $fecha_ini_instancia_format . '</b> hasta: <b style="font-weight:600">' . $fecha_fin_instancia_format . '<b>';







        $data_view['message_label'] = $mensaje_cierre_fechas;



        //Valida la fecha de cierre de la instacia.



        if ($fecha_hoy < $fecha_ini_instancia) {



            $data_view['message'] = $this->get_texto_sistema('no_inicio_proceso_votacion')->TEX_LABEL;



            $data_view['remain_votacion'] = true;



            $this->load->view('errors/error_start_sistema', $data_view);



            return false;
        }



        if ($fecha_hoy > $fecha_fin_instancia) {



            $data_view['message'] = $this->get_texto_sistema('TEX_NOVIGE')->TEX_LABEL;



            $this->load->view('errors/error_start_sistema', $data_view);



            return false;
        }



        return true;
    }







    /**



     * Envía mensaje de texto.



     *



     * @param string $celular



     * @param type $pin



     */



    private function _send_mensaje_texto($celular, $pin)



    {



        //$this->load->library('elibom/elibom');



        //$elibom = new Elibom($this->_configuracion->TEX_USSMS, $this->_configuracion->TEX_PWSMS);











        //Indicativo país.



        $celular     =  $celular;







        $flash_sms = ($this->_configuracion->BOL_FLASHSMS) ? 'true' : 'false';




/*


        $url_sms = 'https://api.masiv.co/SmsHandlers/sendhandler.ashx';



        $user_sms = 'Api_K4OGL';



        $pass_sms = 'h5yIvTxOR1Jh';
*/






        $message_sms = $this->get_texto_sistema('TEX_SMSPW')->TEX_LABEL . ' ' . $pin;



        $message_sms =  str_replace(' ', '+', $message_sms);
         // print_r( $message_sms);die;
        if ($this->_configuracion->BOL_SMS == 1) {
            $this->envia_sms_liwa($celular, $message_sms, TRUE);
        } else {
            $this->envia_sms_sigma($celular, $message_sms, TRUE);
        }











       /* $url_send = "$url_sms?action=sendmessage&username=$user_sms&password=$pass_sms&recipient=$celular&messagedata=$message_sms&flash=$flash_sms&longMessage=true&premium=true";







        $ch = curl_init();



        curl_setopt($ch, CURLOPT_URL, $url_send);



        curl_setopt($ch, CURLOPT_VERBOSE, 0);



        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);







        curl_exec($ch);



        curl_close($ch);







        //$elibom->sendMessage($celular, $message_sms);*/



    }







    /**



     * Envía mensaje de texto.



     *



     * @param string $celular



     * @param type $pin



     */



    private function _send_mensaje_texto_password($participante)



    {







        // print_r($);die;



        // $this->load->library('elibom/elibom');



        //$elibom   = new Elibom($this->_configuracion->TEX_USSMS, $this->_configuracion->TEX_PWSMS);


 $password = $this->_get_password_para_recordar($participante);
       // $password = $this->_generateRandomString();



        if ($password) {



            $update =     $this->Participante->update_password($participante->NUM_IDETER, $password);
        }











        $nombre_empresa       = $this->Empresa->get_nom_empresa();



        $nombre_empresa = $nombre_empresa->TEX_NOMEMP;



        $nombre =  $participante->TEX_NOMPAR;







        $nom = str_replace(array("#", "'", ";", "&"), '', $nombre);











        $message_sms = 'Buen día Sr.(a) , ' . $nom . ' ' . $nombre_empresa . ' ' . $this->get_texto_sistema('TEX_SMSPWSYS')->TEX_LABEL . ' ' . $password;

       // print_r( $message_sms);die;
        if ($this->_configuracion->BOL_SMS == 1) {
            $this->envia_sms_liwa($participante->NUM_TELCEL, $message_sms, TRUE);
        } else {
            $this->envia_sms_sigma($participante->NUM_TELCEL, $message_sms, TRUE);
        }

        // $this->envia_sms($participante->NUM_TELCEL, $message_sms, TRUE);







        /* // codigo Anterior 



        //Indicativo país.



        $celular     = '57' . $participante->NUM_TELCEL;



        



        $flash_sms = ($this->_configuracion->BOL_FLASHSMS)?'true':'false';



        



        $url_sms = 'https://api.masiv.co/SmsHandlers/sendhandler.ashx';



        $user_sms = 'Api_K4OGL';



        $pass_sms = 'h5yIvTxOR1Jh';



        



        $message_sms = $this->get_texto_sistema('TEX_SMSPWSYS')->TEX_LABEL. ' ' . $password;



        $message_sms =  str_replace(' ', '+', $message_sms);



        



       



        



        $url_send = "$url_sms?action=sendmessage&username=$user_sms&password=$pass_sms&recipient=$celular&messagedata=$message_sms&flash=$flash_sms&longMessage=true&premium=true";



        



       



        $ch = curl_init();



        curl_setopt($ch, CURLOPT_URL, $url_send);



        curl_setopt($ch, CURLOPT_VERBOSE, 0);



        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);  



        



        curl_exec($ch);



        curl_close($ch);*/
    }










    function envia_sms_sigma($telefono, $mensaje, $idCategoria = 1, $nombreCampania = null)
    {
        if ($nombreCampania === null) {
            $nombreCampania = 'EVIR_' . date('Ymd_His');
        }

        $indicativos = array("300", "301", "302", "303", "304", "305", "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", "320", "321", "322", "323", "350", "351");
        $indicativo_cliente = substr($telefono, 0, 3);

        if (strlen($telefono) != 10) {
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['ok' => false, 'error' => 'Teléfono inválido (se esperan 10 dígitos).', 'telefono' => $telefono], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            exit;
        }
        if (!in_array($indicativo_cliente, $indicativos)) {
            header('Content-Type: application/json; charset=utf-8');
            echo json_encode(['ok' => false, 'error' => 'El indicativo del celular no está permitido.', 'telefono' => $telefono], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
            exit;
        }

        // ---- Configuración SIGMA (SIN .env) ----
        $API_TOKEN = '21879|zxvWUa6n0YLhxcZXPyF3jGuQuTpSkGiqfyIJ9Jw2b08117bc'; // <--  token
        $API_BASE  = 'https://aio2.sigmamovil.com/api';
        $URL       = rtrim($API_BASE, '/') . '/sms';

        // Algunos tenants usan x-api-key, otros Authorization: Bearer.
        // Déjalos ambos para la prueba; si ves 401/403, elimina el que no aplique.
        $headers = array(
            'x-api-key: ' . $API_TOKEN,
            'Authorization: Bearer ' . $API_TOKEN,
            'Content-Type: application/json',
            'Accept: application/json'
        );

        // Body tipo "lote" (con 1 receptor) como en tu screenshot
        $payload = array(
            'idSmsCategory' => (int)$idCategoria,     // debe existir en tu cuenta Sigma
            'name'          => (string)$nombreCampania,
            'receiver'      => array(
                array(
                    'indicative' => 57,
                    'phone'      => (int)$telefono,   // solo los 10 dígitos
                    'message'    => (string)$mensaje
                )
            ),
            'dateNow'       => 1,                     // 1 = envío inmediato (si quieres programar: usa scheduleDate y pon 0)
            'type'          => 'lote',
            'track'         => 0,
            'flash'         => 0,
            'api'           => 1,
            'notification'  => 0,
            'rne'           => 0
        );

        $ch = curl_init($URL);
        curl_setopt_array($ch, array(
            CURLOPT_POST           => 1,
            CURLOPT_HTTPHEADER     => $headers,
            CURLOPT_POSTFIELDS     => json_encode($payload, JSON_UNESCAPED_UNICODE),
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_TIMEOUT        => 25,
            CURLOPT_VERBOSE        => 0
        ));

        $raw    = curl_exec($ch);
        $errno  = curl_errno($ch);
        $errstr = curl_error($ch);
        $http   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        $json = json_decode($raw, true);
        $ok   = ($http >= 200 && $http < 300);

        // Respuesta visible SIEMPRE
        /*header('Content-Type: application/json; charset=utf-8');
    echo json_encode([
        'ok'      => $ok && !$errno,
        'http'    => $http,
        'url'     => $URL,
        'headers' => $headers,
        'payload' => $payload,
        'curlErr' => $errno ? ('cURL: '.$errstr) : null,
        'raw'     => $raw,
        'json'    => $json
    ], JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
    exit;*/
    }


    function envia_sms_liwa($telefono, $mensaje, $debug)



    {



        $indicativos = array("300", "301", "302", "303", "304", "305", "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", "320", "321", "322", "323", "350", "351");



        $indicativo_cliente = substr($telefono, 0, 3);







        if (strlen($telefono) == 10) {



            if (in_array($indicativo_cliente, $indicativos)) {







                $account = '00486368700';



                //$api_key='dadce556b6a56f8be394a3600a24e977f6fbe970';

                $api_key = '976c108277654b6e83203d1ed6b4826f90ce8dc3';



                $password = 'Cursor91';



                $api_numero_telefono = '57' . $telefono;



                $api_mensaje_texto = $mensaje;



                /***********************************************************************/







                $fullurl = "https://api.liwa.co/v2/auth/login";







                //https://api-dev.cellvoz.com/v2/auth/login _



                //https://api.cellvoz.com/v2/auth/login _







                $headers = array(



                    "Content-Type: application/json",



                );







                $post_params = array(



                    "api_key" => $api_key,



                    "account" => $account,



                    "password" => $password,



                    "Content-type: application/json",



                );



                $post_params = json_encode($post_params);







                $curl = curl_init($fullurl);



                curl_setopt($curl, CURLOPT_POST, 1);



                curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);



                curl_setopt($curl, CURLOPT_POSTFIELDS, $post_params);



                curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);



                curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);



                curl_setopt($curl, CURLOPT_VERBOSE, 1);







                $response = curl_exec($curl);



                $respuesta_final_autentificacion = json_decode($response, true);







                $token_autentificacion = $respuesta_final_autentificacion['token'];





                /********************************************************************/



                $fullurl = "https://api.liwa.co/v2/sms/single"; // "https://api.cellvoz.co/v2/sms/single";







                $headers = array(



                    "api-key: " . $api_key,



                    "Authorization: Bearer " . $token_autentificacion,



                    "Content-Type: application/json",



                );







                $post_params = array(



                    "number" => $api_numero_telefono,



                    "message" => $api_mensaje_texto,



                    "Content-type: application/json",



                );



                $post_params = json_encode($post_params);







                $curl = curl_init($fullurl);



                curl_setopt($curl, CURLOPT_POST, 1);



                curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);



                curl_setopt($curl, CURLOPT_POSTFIELDS, $post_params);



                curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);



                curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);



                curl_setopt($curl, CURLOPT_VERBOSE, 1);







                $response = curl_exec($curl);



                $respuesta_final_envio = json_decode($response, true);



                $mensaje_enviado = $respuesta_final_envio['success'];



                /********************************************************************/







                //if($mensaje_enviado == 1) { $er="Mensaje Enviado"; } else { $er="Mensaje No Enviado"; }







            } else {



                $er = "El indicativo del telefono celular no esta permitido";
            }
        } else {



            $er = "La longitud del telefono celular no concuerda con un numero valido";
        }

        /*





if($debug == true)



	{ 



		echo '<pre>';print_r($respuesta_final_autentificacion);echo '</pre>';



		echo '<pre>';print_r($respuesta_final_envio);echo '</pre>';



		echo $er;



	}



*/
    }







    public function recordar_password()



    {



        $genera_pin = $this->_configuracion->BOL_VALPIN;







        $data_view['images'] = [



            'uploads/backgrounds/tech1.jpg',



            'uploads/backgrounds/tech2.jpg',



            'uploads/backgrounds/tech3.jpg',



            'uploads/backgrounds/tech4.jpg',



            'uploads/backgrounds/tech1.jpg',



            'uploads/backgrounds/tech2.jpg',



            'uploads/backgrounds/tech3.jpg',



            'uploads/backgrounds/tech4.jpg',



        ];



        if ($this->input->post()) {







            if ($this->input->post('cedula')) {



                $cedula = $this->input->post('cedula');



                $datos_participante = $this->Participante->get($cedula);







                if (!$datos_participante) {



                    $data_view['message'] = ['error' => $this->get_texto_sistema('TEX_ERUSNO')->TEX_LABEL];



                    $data_view['titulo']  = 'Recuperar contraseña';



                    $this->load->view('recordar_password', $data_view);



                    return false;
                }















                $validacion_voto_previo = $this->Participante->get_exits_voto(null, $datos_participante->NUM_IDETER, null);







                if ($validacion_voto_previo) {



                    $data_view['message'] = ['error' => $this->get_texto_sistema('TEX_ISVOTO')->TEX_LABEL];



                    $data_view['titulo']  = 'Recuperar contraseña';



                    $this->load->view('recordar_password', $data_view);



                    return false;
                }







                $email_celular            = $this->input->post('email_celular');















                //Validación para el celular o el email que no pertenece al participante



                if (filter_var($email_celular, FILTER_VALIDATE_EMAIL)) {



                    if ($datos_participante->TEX_MAIL !== $email_celular) {



                        $data_view['message'] = ['error' => 'El email no corresponde al que tiene registrado en la base de datos'];



                        $data_view['titulo']  = 'Recuperar contraseña';



                        $this->load->view('recordar_password', $data_view);



                        return false;
                    }
                }







                if (is_numeric($email_celular)) {



                    if ($datos_participante->NUM_TELCEL !== $email_celular) {



                        $data_view['message'] = ['error' => 'El celular no corresponde al que tiene registrado en la base de datos'];



                        $data_view['titulo']  = 'Recuperar contraseña';



                        $this->load->view('recordar_password', $data_view);



                        return false;
                    }
                }







                $datos_envio_mail = $this->Participante->get_participante_by_mail($email_celular);











                if ($datos_envio_mail) {



                    if ($datos_envio_mail->TEX_MAIL) {



                        $data_log = [



                            'NUM_IDETER' => $datos_envio_mail->NUM_IDETER,



                            'TEX_TIPOENVIO' => 'Email',



                            'TEX_IPORIG' => $this->input->ip_address(),



                            'FEC_GENERACION' => date("Y-m-d H:i:s")



                        ];



                        $this->Log_recordar_password->insert($data_log);



                        $send_mail = $this->_enviar_email_recordar_password($datos_participante);



                        $data_view['titulo']     = 'Recuperar contraseña';



                        $data_view['success']     = true;



                        $data_view['message_send']    = 'Se ha enviado via Email su contraseña para acceso al sistema.';



                        $this->load->view('recordar_password', $data_view);



                        return false;
                    }
                }







                $datos_envio_msm = $this->Participante->get_participante_by_sms($email_celular);



                if ($datos_envio_msm) {



                    if ($datos_envio_msm->NUM_TELCEL) {



                        $data_log = [



                            'NUM_IDETER' => $datos_envio_msm->NUM_IDETER,



                            'TEX_TIPOENVIO' => 'SMS',



                            'TEX_IPORIG' => $this->input->ip_address(),



                            'FEC_GENERACION' => date("Y-m-d H:i:s")



                        ];



                        $this->Log_recordar_password->insert($data_log);



                        $this->_send_mensaje_texto_password($datos_envio_msm);



                        $data_view['titulo']  = 'Recuperar contraseña';



                        $data_view['success']     = true;



                        //$data_view['message_send']     = $this->get_texto_sistema('TEX_SMSPWSYS')->TEX_LABEL;



                        $data_view['message_send']     =  'Se ha generado y enviado la contraseña via mensaje de texto';



                        $this->load->view('recordar_password', $data_view);



                        return false;
                    }
                }







                $data_view['message'] = ['error' => $this->get_texto_sistema('TEX_SMSMAILERR')->TEX_LABEL];



                $data_view['titulo']  = 'Recuperar contraseña';



                $this->load->view('recordar_password', $data_view);



                return false;
            }
        } else {



            $data_view['titulo']     = 'Recuperar contraseña';



            $data_view['regresar']   = 0;



            $data_view['genera_pin'] = (bool) $genera_pin;



            $this->load->view('recordar_password', $data_view);
        }
    }







    private function _enviar_email_recordar_password($datos_participante)

    {

        // Generar nueva contraseña

        $password = $this->_get_password_para_recordar($datos_participante);
       // $password = $this->_generateRandomString();



        if ($password) {

            $this->Participante->update_password($datos_participante->NUM_IDETER, $password);
        }



        // Obtener nombre de la empresa

        $nombre_empresa = $this->Empresa->get_nom_empresa()->TEX_NOMEMP;



        // Construir asunto y textos

        $asunto = $nombre_empresa . ' ' . $this->get_texto_sistema('TEX_MAILPWASU')->TEX_LABEL;

        $body   = $this->get_texto_sistema('TEX_MAILPWBOD')->TEX_LABEL;

        $body2  = $this->get_texto_sistema('TEX_MAILPWASUN')->TEX_LABEL;



        // Configuración del remitente y destinatario

        $fromEmail = "info@gestionvir.com";

        $fromName  = "Evir - Votación Virtual";

        $to        = $datos_participante->TEX_MAIL;



        // Cabeceras del correo

        $headers = 'From: ' . $fromName . ' <' . $fromEmail . '>' . "\r\n" .

            'Reply-To: ' . $fromEmail . "\r\n" .

            'X-Mailer: PHP/' . phpversion() . "\r\n" .

            'MIME-Version: 1.0' . "\r\n" .

            'Content-type: text/html; charset=UTF-8';



        // Contenido HTML del mensaje

        $mensaje = "

        <html>

        <head>

            <title>Su contraseña se ha generado.</title>

        </head>

        <body>

            <h3>{$body}</h3>

            <p>Buen día Sr.(a) {$datos_participante->TEX_NOMPAR}</p>

            <p>{$body2} {$nombre_empresa} es: <strong>{$password}</strong></p>

        </body>

        </html>

    ";



        // Enviar el correo

        if (mail($to, $asunto, $mensaje, $headers)) {

            return true; // o manejar como necesites

        } else {

            return false;
        }
    }





    private function _generateRandomString($length = 5)



    {



        $characters = '0123456789';



        if ((bool)$this->_configuracion->BOL_TIPPW) {



            $characters       = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        }



        $charactersLength = strlen($characters);



        $randomString     = '';







        if ($this->_configuracion->NUM_LONGPW) {



            $length = $this->_configuracion->NUM_LONGPW;
        }



        for ($i = 0; $i < $length; $i++) {



            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }



        return $randomString;
    }











    public function get_fecha_inicio_votacion()



    {



        $fecha_instancia = $this->Instancia->get_by(['BOL_ACTIVO' => 1, 'IS_DELETE' => 0]);



        if (!$fecha_instancia) {



            echo json_encode(['fecha_ini_instancia' => 0]);



            return false;
        }



        echo json_encode(['fecha_ini_instancia' => $fecha_instancia->FEC_INIUSO]);



        exit;
    }
}
