<?php
namespace App\Domains\Permission\Services;

use App\Dicts;
use App\Core\Service;
use App\Models\Account\Account;
use App\Models\Permission\Role;
use Illuminate\Validation\Rule;
use App\Exceptions\NotExistException;
use Illuminate\Support\Facades\Validator;
use App\Exceptions\InvalidArgumentException;
use App\Domains\Permission\Repositories\RoleRepository;

class RoleService extends Service
{
    protected $roleRepository;
    protected $dicts;

    /**
     * 构造函数
     *
     * @return void
     */
    public function __construct(RoleRepository $roleRepository, Dicts $dicts)
    {
        $this->roleRepository = $roleRepository;
        $this->dicts = $dicts;
        $this->account = app('dipper')->initAccount();
    }

    /**
     * 角色列表
     *
     * @param array $conditions
     * @return mixed
     */
    public function index(array $conditions = [])
    {
        $limit = $conditions['limit'] ?? 20;

        $roleConditions = [];

        $query = $this->roleRepository->with(['parent'])->withConditions($roleConditions)->applyConditions();

        $roles = $query->paginate($limit);

        $roles->map(function ($role) {
            $role->parent = $role->parent ? $role->parent->name : '';
        });

        return ['roles' => $roles];
    }

    /**
     * 存储角色
     *
     * @param array $attributes
     * @return void
     */
    public function store(array $attributes)
    {
        $attributes = array_only($attributes, ['id', 'parent_id', 'name', 'remark']);

        $rule = [
            'name' => ['display_length:32', Rule::unique($this->roleRepository->getTable())->where(function ($query) use ($attributes) {
                return $query->where('name', $attributes['name']);
            })->ignore($attributes['id'])],
        ];

        $message = [
            'name.unique' => '角色名称必须唯一',
        ];

        Validator::validate($attributes, $rule, $message);

        if ($attributes['parent_id']) {
            $parent = $this->roleRepository->findById($attributes['parent_id']);

            if ($parent->parent_id !== 1) {
                throw new InvalidArgumentException('父级ID不合法');
            }
        }

        if (!$attributes['id']) {
            $role = $this->roleRepository->create($attributes, $parent);
            return $role;
        }

        $role = $this->roleRepository->findById($attributes['id']);

        if ($parent && $role->parent_id !== $parent->id) {
            $role->appendToNode($parent);
        }

        $this->roleRepository->setModel($role)->update($attributes);

        return $role;
    }

    /**
     * 删除
     *
     * @return bool
     */
    public function destroy($ids)
    {
        $ids = is_array($ids) ? $ids : [$ids];

        $this->roleRepository->destroy($ids);

        return true;
    }

    /**
     * 给用户分配角色
     *
     * @param Account|int $accountId
     * @param string|array|Role|Collection $roles
     * @return void
     */
    public function syncRoles($accountId, ...$roles)
    {
        if ($accountId instanceof Account) {
            $account = $accountId;
        } else {
            $account = Account::where('id', $accountId)->firstOr(function () {
                throw new NotExistException('账号不存在或已删除');
            });
        }

        $account->syncRoles($roles);

        return true;
    }

    /**
     * 分配权限
     *
     * @param string|array|Permission|Collection $permissions
     * @return void
     */
    public function syncPermissions($roleId, ...$permissions)
    {
        if ($roleId instanceof Role) {
            $role = $roleId;
        } else {
            $role = $this->roleRepository->findById($roleId);
        }

        $role->syncPermissions($permissions);
        return true;
    }
}
