<?php
class Usuario
{
    private $conn;

    public function __construct($db)
    {
        $this->conn = $db;
    }

    public function login($username, $password)
    {
        try {
            // Buscar el usuario por username o email
            $query = "SELECT * FROM usuarios WHERE (username = :username OR email = :email) AND activo = 1";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':username', $username);
            $stmt->bindParam(':email', $username);
            $stmt->execute();

            $usuario = $stmt->fetch(PDO::FETCH_ASSOC);

            if ($usuario && password_verify($password, $usuario['password_hash'])) {
                error_log("Login - Password verificado correctamente");

                // Actualizar último acceso
                $this->actualizarUltimoAcceso($usuario['id']);

                // Obtener roles
                $queryRoles = "SELECT GROUP_CONCAT(r.nombre) as roles 
                               FROM usuario_roles ur 
                               LEFT JOIN roles r ON ur.rol_id = r.id 
                               WHERE ur.usuario_id = :usuario_id";

                $stmtRoles = $this->conn->prepare($queryRoles);
                $stmtRoles->bindParam(':usuario_id', $usuario['id']);
                $stmtRoles->execute();
                $rolesData = $stmtRoles->fetch(PDO::FETCH_ASSOC);

                $usuario['roles'] = $rolesData['roles'] ?? '';
                error_log("Login - Roles: " . $usuario['roles']);

                // Obtener permisos
                $permisos = $this->obtenerPermisos($usuario['id']);
                error_log("Login - Permisos obtenidos: " . json_encode($permisos));

                unset($usuario['password_hash']);
                $usuario['permisos'] = $permisos;

                return $usuario;
            } else {
                error_log("Login - Password incorrecto o usuario no encontrado");
            }

            return false;
        } catch (Exception $e) {
            error_log("Error en login: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            return false;
        }
    }

    public function obtenerPermisos($usuarioId)
    {
        try {
            $query = "SELECT DISTINCT 
                        m.nombre as modulo,
                        m.ruta,
                        m.icono,
                        p.nombre as permiso
                      FROM usuarios u
                      JOIN usuario_roles ur ON u.id = ur.usuario_id
                      JOIN rol_modulo_permisos rmp ON ur.rol_id = rmp.rol_id
                      JOIN modulos m ON rmp.modulo_id = m.id
                      JOIN permisos p ON rmp.permiso_id = p.id
                      WHERE u.id = :usuario_id AND m.activo = 1
                      ORDER BY m.orden, p.nombre";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':usuario_id', $usuarioId);
            $stmt->execute();

            $resultados = $stmt->fetchAll(PDO::FETCH_ASSOC);

            $permisos = [];
            foreach ($resultados as $row) {
                $modulo = $row['modulo'];
                if (!isset($permisos[$modulo])) {
                    $permisos[$modulo] = [
                        'ruta' => $row['ruta'],
                        'icono' => $row['icono'],
                        'permisos' => []
                    ];
                }
                $permisos[$modulo]['permisos'][] = $row['permiso'];
            }

            return $permisos;
        } catch (Exception $e) {
            error_log("Error obteniendo permisos: " . $e->getMessage());
            return [];
        }
    }

    public function verificarPermiso($usuarioId, $modulo, $permiso)
    {
        try {
            $query = "SELECT COUNT(*) as tiene_permiso
                      FROM usuarios u
                      JOIN usuario_roles ur ON u.id = ur.usuario_id
                      JOIN rol_modulo_permisos rmp ON ur.rol_id = rmp.rol_id
                      JOIN modulos m ON rmp.modulo_id = m.id
                      JOIN permisos p ON rmp.permiso_id = p.id
                      WHERE u.id = :usuario_id 
                        AND m.nombre = :modulo 
                        AND p.nombre = :permiso 
                        AND m.activo = 1";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':usuario_id', $usuarioId);
            $stmt->bindParam(':modulo', $modulo);
            $stmt->bindParam(':permiso', $permiso);
            $stmt->execute();

            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            return $result['tiene_permiso'] > 0;
        } catch (Exception $e) {
            error_log("Error verificando permiso: " . $e->getMessage());
            return false;
        }
    }

    public function crear($datos)
    {
        try {
            $query = "INSERT INTO usuarios (username, email, password_hash, nombre, apellido, telefono) 
                      VALUES (:username, :email, :password_hash, :nombre, :apellido, :telefono)";

            $stmt = $this->conn->prepare($query);

            $passwordHash = password_hash($datos['password'], PASSWORD_BCRYPT);

            $stmt->bindParam(':username', $datos['username']);
            $stmt->bindParam(':email', $datos['email']);
            $stmt->bindParam(':password_hash', $passwordHash);
            $stmt->bindParam(':nombre', $datos['nombre']);
            $stmt->bindParam(':apellido', $datos['apellido']);
            $stmt->bindParam(':telefono', $datos['telefono']);

            $stmt->execute();

            return $this->conn->lastInsertId();
        } catch (Exception $e) {
            error_log("Error creando usuario: " . $e->getMessage());
            return false;
        }
    }

    public function obtenerPorId($id)
    {
        try {
            $query = "SELECT u.id, u.username, u.email, u.nombre, u.apellido, u.telefono, 
                             u.activo, u.ultimo_acceso, u.created_at,
                             GROUP_CONCAT(r.nombre) as roles
                      FROM usuarios u 
                      LEFT JOIN usuario_roles ur ON u.id = ur.usuario_id 
                      LEFT JOIN roles r ON ur.rol_id = r.id 
                      WHERE u.id = :id 
                      GROUP BY u.id";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':id', $id);
            $stmt->execute();

            return $stmt->fetch(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error obteniendo usuario: " . $e->getMessage());
            return false;
        }
    }

    public function obtenerTodos()
    {
        try {
            $query = "SELECT u.id, u.username, u.email, u.nombre, u.apellido, u.telefono, 
                             u.activo, u.ultimo_acceso, u.created_at,
                             GROUP_CONCAT(r.nombre) as roles
                      FROM usuarios u 
                      LEFT JOIN usuario_roles ur ON u.id = ur.usuario_id 
                      LEFT JOIN roles r ON ur.rol_id = r.id 
                      GROUP BY u.id 
                      ORDER BY u.created_at DESC";

            $stmt = $this->conn->prepare($query);
            $stmt->execute();

            return $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Exception $e) {
            error_log("Error obteniendo usuarios: " . $e->getMessage());
            return [];
        }
    }

    public function asignarRol($usuarioId, $rolId)
    {
        try {
            $query = "INSERT IGNORE INTO usuario_roles (usuario_id, rol_id) VALUES (:usuario_id, :rol_id)";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':usuario_id', $usuarioId);
            $stmt->bindParam(':rol_id', $rolId);

            return $stmt->execute();
        } catch (Exception $e) {
            error_log("Error asignando rol: " . $e->getMessage());
            return false;
        }
    }

    private function actualizarUltimoAcceso($usuarioId)
    {
        try {
            $query = "UPDATE usuarios SET ultimo_acceso = CURRENT_TIMESTAMP WHERE id = :id";
            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':id', $usuarioId);
            $stmt->execute();
        } catch (Exception $e) {
            error_log("Error actualizando último acceso: " . $e->getMessage());
        }
    }

    public function guardarSesion($usuarioId, $tokenHash, $ipAddress, $userAgent, $expiresAt)
    {
        try {
            $query = "INSERT INTO sesiones (usuario_id, token_hash, ip_address, user_agent, expires_at) 
                      VALUES (:usuario_id, :token_hash, :ip_address, :user_agent, :expires_at)";

            $stmt = $this->conn->prepare($query);
            $stmt->bindParam(':usuario_id', $usuarioId);
            $stmt->bindParam(':token_hash', $tokenHash);
            $stmt->bindParam(':ip_address', $ipAddress);
            $stmt->bindParam(':user_agent', $userAgent);
            $stmt->bindParam(':expires_at', $expiresAt);

            return $stmt->execute();
        } catch (Exception $e) {
            error_log("Error guardando sesión: " . $e->getMessage());
            return false;
        }
    }
}
