<?php
class NexoraRbac {
    private static $cfg;
    private static $dbRoles = array();
    private static $dbPermissions = array();

    private static function cfg() {
        if(is_array(self::$cfg)) return self::$cfg;
        $file = __PATH_CONFIGS__ . 'nexora.rbac.php';
        self::$cfg = is_file($file) ? include($file) : array('roles'=>array(),'users'=>array(),'module_permissions'=>array());
        return self::$cfg;
    }

    private static function platformRolesFor($username) {
        $username = (string)$username;
        if($username === '' || !class_exists('NexoraRealm') || !NexoraRealm::platformEnabled()) return array();
        if(array_key_exists($username, self::$dbRoles)) return self::$dbRoles[$username];
        try {
            $db = Connection::Database('Platform');
            $rows = $db->query_fetch('SELECT role_key FROM NEXORA_USER_ROLES WHERE username = ?', array($username));
            $roles = array();
            if(is_array($rows)) foreach($rows as $row) if(!empty($row['role_key'])) $roles[] = $row['role_key'];
            self::$dbRoles[$username] = array_values(array_unique($roles));
        } catch(Throwable $e) {
            self::$dbRoles[$username] = array();
        }
        return self::$dbRoles[$username];
    }

    private static function permissionsForRole($role) {
        $cfg = self::cfg();
        $permissions = isset($cfg['roles'][$role]) && is_array($cfg['roles'][$role]) ? $cfg['roles'][$role] : array();
        if(!class_exists('NexoraRealm') || !NexoraRealm::platformEnabled()) return $permissions;
        if(array_key_exists($role, self::$dbPermissions)) return array_values(array_unique(array_merge($permissions, self::$dbPermissions[$role])));
        try {
            $db = Connection::Database('Platform');
            $rows = $db->query_fetch('SELECT permission_key FROM NEXORA_ROLE_PERMISSIONS WHERE role_key = ?', array($role));
            $dbPermissions = array();
            if(is_array($rows)) foreach($rows as $row) if(!empty($row['permission_key'])) $dbPermissions[] = $row['permission_key'];
            self::$dbPermissions[$role] = $dbPermissions;
        } catch(Throwable $e) {
            self::$dbPermissions[$role] = array();
        }
        return array_values(array_unique(array_merge($permissions, self::$dbPermissions[$role])));
    }

    public static function rolesFor($username) {
        $cfg = self::cfg();
        $roles = isset($cfg['users'][$username]) && is_array($cfg['users'][$username]) ? $cfg['users'][$username] : array();
        $roles = array_merge($roles, self::platformRolesFor($username));
        $legacyAdmins = config('admins', true);
        if(is_array($legacyAdmins) && array_key_exists($username, $legacyAdmins) && !in_array('superadmin', $roles, true)) $roles[] = 'superadmin';
        return array_values(array_unique($roles));
    }

    public static function canAccess($username) {
        return count(self::rolesFor((string)$username)) > 0;
    }

    public static function has($username, $permission) {
        foreach(self::rolesFor((string)$username) as $role) {
            $permissions = self::permissionsForRole($role);
            if(in_array('*', $permissions, true) || in_array($permission, $permissions, true)) return true;
        }
        return false;
    }

    public static function permissionForModule($module) {
        $cfg = self::cfg();
        return isset($cfg['module_permissions'][$module]) ? $cfg['module_permissions'][$module] : 'system.manage';
    }

    public static function requirePermission($permission) {
        $username = isset($_SESSION['username']) ? $_SESSION['username'] : '';
        if(!$username || !self::has($username, $permission)) {
            http_response_code(403);
            throw new RuntimeException('No tienes permiso para ejecutar esta operación.');
        }
        return true;
    }

    public static function clearRuntimeCache() {
        self::$dbRoles = array();
        self::$dbPermissions = array();
    }
}
