<?php

declare(strict_types=1);

namespace Kylin\Rbac\Policies;

use Illuminate\Foundation\Auth\User as Authenticatable;

/**
 * RBAC 基础策略类
 *
 * 为所有业务 Policy 提供统一的 RBAC 权限校验基础。
 * 使用方式：业务 Policy 继承此类，实现具体权限方法。
 *
 * 示例：
 *   class OrderPolicy extends BasePolicy
 *   {
 *       public function viewAny(Authenticatable $user): bool
 *       {
 *           return $this->checkPermission($user, 'order.view');
 *       }
 *   }
 *
 * 依据等保 2.0 (GB/T 22239) 8.1.4.1：最小权限原则
 * 依据等保 2.0 (GB/T 22239) 8.1.4.3：基于角色的访问控制
 */
class BasePolicy
{
    /**
     * 检查用户是否拥有指定权限
     *
     * 先检查直接权限，再检查角色关联权限。
     */
    protected function checkPermission(Authenticatable $user, string $permission): bool
    {
        if (! method_exists($user, 'hasPermissionTo')) {
            return false;
        }
        return $user->hasPermissionTo($permission);
    }

    /**
     * 检查用户是否拥有任一权限
     *
     * @param  string[]  $permissions
     */
    protected function checkAnyPermission(Authenticatable $user, array $permissions): bool
    {
        foreach ($permissions as $permission) {
            if ($this->checkPermission($user, $permission)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查用户是否拥有全部权限
     *
     * @param  string[]  $permissions
     */
    protected function checkAllPermissions(Authenticatable $user, array $permissions): bool
    {
        foreach ($permissions as $permission) {
            if (! $this->checkPermission($user, $permission)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 检查用户是否拥有指定角色
     */
    protected function checkRole(Authenticatable $user, string $role): bool
    {
        if (! method_exists($user, 'hasRole')) {
            return false;
        }
        return $user->hasRole($role);
    }

    /**
     * 超级管理员绕过所有权限检查
     *
     * 依据等保 2.0，超级管理员仍需审计，但可绕过常规权限检查。
     */
    protected function isSuperAdmin(Authenticatable $user): bool
    {
        return $this->checkRole($user, 'super-admin');
    }
}