<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Auth_model extends CI_Model {

    private $max_intentos = 5;
    private $tiempo_bloqueo = 30; // minutos

    public function __construct() {
        parent::__construct();
        $this->load->database();
    }

    /**
     * Verificar credenciales del usuario
     */
    public function verificar_login($username, $password) {
        // Buscar usuario por username o email
        $this->db->where('username', $username);
        $this->db->or_where('email', $username);
        $usuario = $this->db->get('usuarios')->row();

        if (!$usuario) {
            $this->registrar_log(null, $username, 'login_fallido', 'Usuario no existe');
            return array('success' => false, 'message' => 'Credenciales incorrectas');
        }

        // Verificar si el usuario está activo
        if ($usuario->activo != 1) {
            $this->registrar_log($usuario->id, $usuario->username, 'login_bloqueado', 'Usuario inactivo');
            return array('success' => false, 'message' => 'Usuario desactivado. Contacte al administrador');
        }

        // Verificar si está bloqueado temporalmente
        if ($usuario->bloqueado_hasta && strtotime($usuario->bloqueado_hasta) > time()) {
            $minutos_restantes = ceil((strtotime($usuario->bloqueado_hasta) - time()) / 60);
            $this->registrar_log($usuario->id, $usuario->username, 'login_bloqueado', 'Cuenta bloqueada temporalmente');
            return array('success' => false, 'message' => "Cuenta bloqueada. Intente nuevamente en {$minutos_restantes} minutos");
        }

        // Verificar password
        if (!password_verify($password, $usuario->password)) {
            $this->incrementar_intentos_fallidos($usuario->id);
            $intentos_restantes = $this->max_intentos - ($usuario->intentos_fallidos + 1);
            
            if ($intentos_restantes <= 0) {
                $this->bloquear_usuario($usuario->id);
                $this->registrar_log($usuario->id, $usuario->username, 'login_bloqueado', 'Máximo de intentos alcanzado');
                return array('success' => false, 'message' => 'Cuenta bloqueada por múltiples intentos fallidos. Intente en ' . $this->tiempo_bloqueo . ' minutos');
            }

            $this->registrar_log($usuario->id, $usuario->username, 'login_fallido', 'Contraseña incorrecta');
            return array('success' => false, 'message' => "Credenciales incorrectas. Intentos restantes: {$intentos_restantes}");
        }

        // Login exitoso - resetear intentos fallidos
        $this->resetear_intentos_fallidos($usuario->id);
        $this->actualizar_ultimo_acceso($usuario->id);
        $this->registrar_log($usuario->id, $usuario->username, 'login_exitoso', 'Login exitoso');

        return array('success' => true, 'usuario' => $usuario);
    }

    /**
     * Incrementar intentos fallidos
     */
    private function incrementar_intentos_fallidos($usuario_id) {
        $this->db->set('intentos_fallidos', 'intentos_fallidos + 1', FALSE);
        $this->db->where('id', $usuario_id);
        $this->db->update('usuarios');
    }

    /**
     * Resetear intentos fallidos
     */
    private function resetear_intentos_fallidos($usuario_id) {
        $this->db->where('id', $usuario_id);
        $this->db->update('usuarios', array(
            'intentos_fallidos' => 0,
            'bloqueado_hasta' => NULL
        ));
    }

    /**
     * Bloquear usuario temporalmente
     */
    private function bloquear_usuario($usuario_id) {
        $bloqueado_hasta = date('Y-m-d H:i:s', strtotime("+{$this->tiempo_bloqueo} minutes"));
        $this->db->where('id', $usuario_id);
        $this->db->update('usuarios', array(
            'bloqueado_hasta' => $bloqueado_hasta
        ));
    }

    /**
     * Actualizar último acceso
     */
    private function actualizar_ultimo_acceso($usuario_id) {
        $this->db->where('id', $usuario_id);
        $this->db->update('usuarios', array(
            'ultimo_acceso' => date('Y-m-d H:i:s')
        ));
    }

    /**
     * Registrar en log de accesos
     */
    public function registrar_log($usuario_id, $username, $accion, $detalles = '') {
        $data = array(
            'usuario_id' => $usuario_id,
            'username' => $username,
            'accion' => $accion,
            'ip_address' => $this->input->ip_address(),
            'user_agent' => $this->input->user_agent(),
            'detalles' => $detalles
        );
        $this->db->insert('log_accesos', $data);
    }

    /**
     * Crear sesión segura
     */
    public function crear_sesion($usuario_id) {
        $session_id = session_id();
        $data = array(
            'usuario_id' => $usuario_id,
            'session_id' => $session_id,
            'ip_address' => $this->input->ip_address(),
            'user_agent' => $this->input->user_agent(),
            'ultimo_actividad' => date('Y-m-d H:i:s')
        );
        $this->db->insert('sesiones', $data);
    }

    /**
     * Eliminar sesión
     */
    public function eliminar_sesion($usuario_id) {
        $this->db->where('usuario_id', $usuario_id);
        $this->db->delete('sesiones');
    }

    /**
     * Validar sesión activa
     */
    public function validar_sesion($usuario_id) {
        $session_id = session_id();
        
        $this->db->where('usuario_id', $usuario_id);
        $this->db->where('session_id', $session_id);
        $sesion = $this->db->get('sesiones')->row();

        if (!$sesion) {
            return false;
        }

        // Verificar timeout de sesión (30 minutos de inactividad)
        $timeout = 1800; // 30 minutos en segundos
        $ultimo_actividad = strtotime($sesion->ultimo_actividad);
        
        if ((time() - $ultimo_actividad) > $timeout) {
            $this->eliminar_sesion($usuario_id);
            return false;
        }

        // Actualizar última actividad
        $this->db->where('id', $sesion->id);
        $this->db->update('sesiones', array(
            'ultimo_actividad' => date('Y-m-d H:i:s')
        ));

        return true;
    }

    /**
     * Generar token de recuperación
     */
    public function generar_token_recuperacion($email) {
        $this->db->where('email', $email);
        $usuario = $this->db->get('usuarios')->row();

        if (!$usuario) {
            return false;
        }

        $token = bin2hex(random_bytes(32));
        $expiracion = date('Y-m-d H:i:s', strtotime('+1 hour'));

        $this->db->where('id', $usuario->id);
        $this->db->update('usuarios', array(
            'token_recuperacion' => $token,
            'token_expiracion' => $expiracion
        ));

        return array('token' => $token, 'email' => $email, 'nombre' => $usuario->nombre_completo);
    }

    /**
     * Validar token de recuperación
     */
    public function validar_token_recuperacion($token) {
        $this->db->where('token_recuperacion', $token);
        $this->db->where('token_expiracion >', date('Y-m-d H:i:s'));
        $usuario = $this->db->get('usuarios')->row();

        return $usuario ? $usuario : false;
    }

    /**
     * Cambiar contraseña
     */
    public function cambiar_password($usuario_id, $nueva_password) {
        $password_hash = password_hash($nueva_password, PASSWORD_BCRYPT, array('cost' => 12));
        
        $this->db->where('id', $usuario_id);
        return $this->db->update('usuarios', array(
            'password' => $password_hash,
            'token_recuperacion' => NULL,
            'token_expiracion' => NULL
        ));
    }

    /**
     * Obtener usuario por ID
     */
    public function get_usuario($usuario_id) {
        return $this->db->get_where('usuarios', array('id' => $usuario_id))->row();
    }
}