<?php
// +----------------------------------------------------------------------
// | onezan-admin 快速开发的管理平台
// +----------------------------------------------------------------------
// | 官方网址：https://www.onezan.cn
// +----------------------------------------------------------------------
// | onezan团队 版权所有 开源版本可自由商用
// +----------------------------------------------------------------------
// | Author: 543885307@qq.com
// +----------------------------------------------------------------------
namespace app\service\domain\admin;

use app\model\AdminRole;
use app\model\AdminRoleUser;
use app\model\AdminUser;
use Core\service\registry\AdminPermissionRegistry;
use think\Collection;


/**
 * 后台权限服务
 * 提供管理员权限查询、角色分配、授权树构建等功能
 * @package app\service\domain\admin
 */
class CoreAdminPermissionService
{
    private AdminPermissionRegistry $registry;

    /**
     * 构造函数
     * @param AdminPermissionRegistry $registry
     */
    public function __construct(AdminPermissionRegistry $registry)
    {
        $this->registry = $registry;
    }

    /**
     * 获取权限注册
     * @return AdminPermissionRegistry
     */
    public function getRegistry(): AdminPermissionRegistry
    {
        return $this->registry;
    }

    /**
     * 获取用户已授权的权限
     * @param AdminUser $user
     * @return array
     */
    public function getGrantedPermissionsForUser(AdminUser $user): array
    {
        if ($user->username === 'admin') {
            return ['*'];
        }

        $roleIds = AdminRoleUser::where('admin_user_id', (int)$user->id)->column('role_id');
        if (!$roleIds) {
            return [];
        }

        $roles = AdminRole::whereIn('id', $roleIds)->where('status', 1)->select();
        $permissions = [];

        foreach ($roles as $role) {
            $raw = (string)$role->permissions;
            if ($raw === '') {
                continue;
            }
            $decoded = json_decode($raw, true);
            if (!is_array($decoded)) {
                continue;
            }
            foreach ($decoded as $permission) {
                if (!is_string($permission)) {
                    continue;
                }
                $permissions[] = $permission;
            }
        }

        return $this->registry->normalizePermissions($permissions, true);
    }

    /**
     * 获取用户已授权的权限（包含角色权限）
     * @param AdminUser $user
     * @return array
     */
    public function getResolvedPermissionsForUser(AdminUser $user): array
    {
        return $this->registry->expandPermissions($this->getGrantedPermissionsForUser($user));
    }

    /**
     * 检查用户是否具有指定权限
     * @param AdminUser $user
     * @param string $requiredPermission
     * @return bool True if the user has the permission, false otherwise
     */
    public function userCan(AdminUser $user, string $requiredPermission): bool
    {
        return $this->registry->hasPermission($this->getGrantedPermissionsForUser($user), $requiredPermission);
    }

    /**
     * 获取用户可授权的权限树
     * @param AdminUser $user
     * @return array
     */
    public function getGrantableTreeForUser(AdminUser $user): array
    {
        if ($user->username === 'admin') {
            return $this->registry->getTree();
        }

        return $this->registry->filterTreeByPermissions($this->getGrantedPermissionsForUser($user));
    }

    /**
     * 检查用户是否可以授权指定权限
     * @param AdminUser $user
     * @param array $permissions
     * @return bool True if the user can grant the permissions, false otherwise
     */
    public function canGrantPermissions(AdminUser $user, array $permissions): bool
    {
        if ($user->username === 'admin') {
            return true;
        }

        $normalized = $this->registry->normalizePermissions($permissions, false);
        if (count($normalized) !== count(array_values(array_filter($permissions, fn ($item) => is_string($item) && trim($item) !== '')))) {
            return false;
        }

        $granted = $this->getGrantedPermissionsForUser($user);
        foreach ($normalized as $permission) {
            if (!$this->registry->hasPermission($granted, $permission)) {
                return false;
            }
        }

        return true;
    }

    /**
     * 获取用户可分配的角色
     * @param AdminUser $user
     * @return Collection
     */
    public function getAssignableRolesForUser(AdminUser $user): Collection
    {
        $roles = AdminRole::where('status', 1)->order('id', 'desc')->select();
        if ($user->username === 'admin') {
            return $roles;
        }

        $assignable = [];
        foreach ($roles as $role) {
            $permissions = $this->decodeRolePermissions($role);
            if ($this->canGrantPermissions($user, $permissions)) {
                $assignable[] = $role;
            }
        }

        return new Collection($assignable);
    }

    /**
     * 获取用户可分配的角色ID
     * @param AdminUser $user
     * @return array
     */
    public function getAssignableRoleIdsForUser(AdminUser $user): array
    {
        return $this->getAssignableRolesForUser($user)->column('id');
    }

    /**
     * 解码角色权限
     * @param AdminRole $role
     * @return array
     */
    private function decodeRolePermissions(AdminRole $role): array
    {
        $raw = (string)$role->permissions;
        if ($raw === '') {
            return [];
        }

        $decoded = json_decode($raw, true);
        if (!is_array($decoded)) {
            return [];
        }

        $permissions = [];
        foreach ($decoded as $permission) {
            if (is_string($permission) && trim($permission) !== '') {
                $permissions[] = trim($permission);
            }
        }

        return $permissions;
    }
}
