<?php

namespace plugin\admin\app\controller;

use plugin\admin\app\common\Auth;
use plugin\admin\app\common\Tree;
use app\model\UserRole as UserRoleModel;
use app\model\UserRule as UserRuleModel;
use support\exception\BusinessException;
use support\Request;
use support\Response;
use Throwable;

/**
 * 角色管理
 */
class UserRoleController extends Crud
{
    /**
     * 不需要鉴权的方法
     * @var array
     */
    protected $noNeedAuth = ['select'];

    /**
     * @var UserRoleModel
     */
    protected $model = null;

    /**
     * 构造函数
     */
    function __construct()
    {
        $this->model = new UserRoleModel;
    }

    /**
     * 浏览
     * @return Response
     * @throws Throwable
     */
    public function index(Request $request): Response
    {
        return view('user_role/index');
    }

    /**
     * 查询
     * @param Request $request
     * @return Response
     * @throws BusinessException
     */
    public function select(Request $request): Response
    {
        [$where, $format, $limit, $field, $order] = $this->selectInput($request);
        $limit = 100000;
        $query = $this->doSelect($where, $field, $order);
        return $this->doFormat($query, $format, $limit);
    }
 
    /**
     * 插入
     * @param Request $request
     * @return Response
     * @throws BusinessException
     * @throws Throwable
     */
    public function insert(Request $request): Response
    {
        if ($request->method() === 'POST') {
            $data = $this->insertInput($request);
            $pid = $data['pid'] ?? null;
            // if (!$pid) {
            //     return $this->fail('请选择父级角色组');
            // }
            if($pid){
                if (!Auth::isSuperAdmin() && !in_array($pid, Auth::getScopeRoleIds(true))) {
                    return $this->fail('父级角色组超出权限范围');
                }
            }
            $this->checkRules($pid, $data['rules'] ?? '');

            $id = $this->doInsert($data);
            return $this->success("操作成功", ['id' => $id]);
        }
        return view('user_role/update',[
            'rolelist'=>    $this->model->select()
        ]);
    }

    /**
     * 更新
     * @param Request $request
     * @return Response
     * @throws BusinessException|Throwable
     */
    public function update(Request $request): Response
    {
        if ($request->method() === 'GET') {
            return view('user_role/update',[
                'rolelist'=>    $this->model->select(),
                'row'   =>  $this->model->whereIn('id',Request()->get('ids'))->findOrEmpty()

            ]);
        }
        [$id, $data] = $this->updateInput($request);
        $is_supper_admin = Auth::isSuperAdmin();
        $descendant_role_ids = Auth::getScopeRoleIds();
        $role = UserRoleModel::find($id);
        if (!$role) {
            return $this->fail('数据不存在');
        }

        if (key_exists('pid', $data) && $data['pid']) {
            $pid = $data['pid'];
            // if (!$pid) {
            //     return $this->fail('请选择父级角色组');
            // }
            if ($pid == $id) {
                return $this->fail('父级不能是自己');
            }
            if (!$is_supper_admin && !in_array($pid, Auth::getScopeRoleIds(true))) {
                return $this->fail('父级超出权限范围');
            }
        } else {
            $pid = $role->pid;
        }
        $this->checkRules($pid, $data['rules'] ?? '');
        $this->doUpdate($id, $data);

        // 删除所有子角色组中已经不存在的权限
        $tree = new Tree(UserRoleModel::field(['id', 'pid'])->select());
        $descendant_roles = $tree->getDescendant([$id]);
        $descendant_role_ids = array_column($descendant_roles, 'id');
        $rule_ids = $data['rules'] ? explode(',', $data['rules']) : [];
        foreach ($descendant_role_ids as $role_id) {
            $tmp_role = UserRoleModel::find($role_id);
            $tmp_rule_ids = $role->getRuleIds();
            $tmp_rule_ids = array_intersect(explode(',',$tmp_role->rules), $tmp_rule_ids);
            $tmp_role->rules = implode(',', $tmp_rule_ids);
            $tmp_role->save();
        }

        return $this->success("操作成功");
    }

    /**
     * 删除
     * @param Request $request
     * @return Response
     * @throws BusinessException
     */
    public function delete(Request $request): Response
    {
        $ids = $this->deleteInput($request);
        if (in_array(1, $ids)) {
            return $this->fail('无法删除超级管理员角色');
        }
        if (!Auth::isSuperAdmin() && array_diff($ids, Auth::getScopeRoleIds())) {
            return $this->fail('无删除权限');
        }
        $tree = new Tree(UserRoleModel::select());
        $descendants = $tree->getDescendant($ids);
        if ($descendants) {
            $ids = array_merge($ids, array_column($descendants, 'id'));
        }
        $this->doDelete($ids);
        return $this->success("操作成功");
    }

    /**
     * 获取角色权限
     * @param Request $request
     * @return Response
     */
    public function rules(Request $request): Response
    {
        $role_id = $request->get('id');
        if (empty($role_id)) {
            return $this->success("操作成功", []);
        }
        if (!Auth::isSuperAdmin() && !in_array($role_id, Auth::getScopeRoleIds(true))) {
            return $this->fail('角色组超出权限范围');
        }
        $rule_id_string = UserRoleModel::where('id', $role_id)->value('rules');
        if ($rule_id_string === '') {
            return $this->success("操作成功", []);
        }
        $rules = UserRuleModel::select();
        $include = [];
        if ($rule_id_string !== '*') {
            $include = explode(',', $rule_id_string);
        }
        $items = [];
        foreach ($rules as $item) {
            $items[] = [
                'name' => $item->title ?? $item->name ?? $item->id,
                'value' => (string)$item->id,
                'id' => $item->id,
                'pid' => $item->pid,
            ];
        }
        $tree = new Tree($items);
        return $this->success("操作成功", $tree->getTree($include));
    }

    /**
     * 检查权限字典是否合法
     * @param int $role_id
     * @param $rule_ids
     * @return void
     * @throws BusinessException
     */
    protected function checkRules(int|string|null $role_id, $rule_ids)
    {
        if ($rule_ids && $role_id>0) {
            $rule_ids = explode(',', $rule_ids);
            if (in_array('*', $rule_ids)) {
                throw new BusinessException('非法数据');
            }
            $rule_exists = UserRuleModel::whereIn('id', $rule_ids)->column('id');
            if (count($rule_exists) != count($rule_ids)) {
                throw new BusinessException('权限不存在');
            }
            $rule_id_string = UserRoleModel::where('id', $role_id)->value('rules');
            if ($rule_id_string === '') {
                throw new BusinessException('数据超出权限范围');
            }
            if ($rule_id_string === '*') {
                return;
            }
            $legal_rule_ids = explode(',', $rule_id_string);
            if (array_diff($rule_ids, $legal_rule_ids)) {
                throw new BusinessException('数据超出权限范围');
            }
        }
    }
    public function tree(Request $request): Response
    {
        $id = $request->post('id');
        $pid = $request->post('pid');
        $parent_rules = '*';
        if($pid){
            $parent_rules = UserRoleModel::where('id', $pid)->value('rules') ?: '';
        }
        if($parent_rules == '*'){
            $rules = UserRuleModel::where('status',1)->Field('id,title as text,pid as parent,"menu" as type')->select();
        }else{
            $rules = UserRuleModel::whereIn('id', $parent_rules)->where('status',1)->Field('id,title as text,pid as parent,"menu" as type')->select();
        }
        $selected_ids = '';
        if($id){
            $selected_ids = UserRoleModel::where('id', $id)->value('rules') ?:'';
        }
        if($selected_ids == '*'){
            $rules->each(function($item){
                $item->state = ['selected'=>false];
                return $item;
            });
        }else{
            $selected_ids = explode(',',$selected_ids);
            $rules->each(function($item)use($selected_ids){
                $state = ['selected'=>false];
                if(in_array($item->id, $selected_ids)){
                    $state['selected'] = true;
                }
                $item->state = $state;
                // if($item->parent == 0){
                //     $item->parent = '#';
                // }
                return $item;
            });
        }
        $rules->push([
            'id'        =>  0,
            'parent'    => '#',
            'text'      => '全部',
            'type'      => 'menu',
        ]);

        return $this->success('ok',$rules);
    }


}
