package com.ho.user.service.impl;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.constant.RedisKeyConstant;
import com.ho.common.tools.entity.PageVO;
import com.ho.common.tools.entity.SimpleUser;
import com.ho.common.tools.entity.SysPermission;
import com.ho.common.tools.entity.UserDetailRespVO;
import com.ho.common.tools.exception.BaseResponseCode;
import com.ho.common.tools.exception.BusinessException;
import com.ho.common.tools.service.RedisService;
import com.ho.common.tools.util.PageUtilsOld;
import com.ho.user.api.entity.PermStationRelation;
import com.ho.user.api.vo.req.QueryPermissionReqVo;
import com.ho.user.entity.PermissionRespNode;
import com.ho.user.mapper.SysPermissionMapper;
import com.ho.user.service.*;
import com.ho.user.util.TokenSettings;
import com.ho.user.vo.req.PermissionAddReqVO;
import com.ho.user.vo.req.PermissionPageReqVO;
import com.ho.user.vo.req.PermissionUpdateReqVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 菜单权限类
 */
@Service
@Slf4j
public class PermissionServiceImpl implements PermissionService {

    @Resource
    private RedisService redisService;

    @Autowired
    @Lazy
    private RedisUpdateService redisUpdateService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    PermStationRelationService permStationRelationService;

    @Autowired
    private RolePermissionService rolePermissionService;

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Autowired
    private TokenSettings tokenSettings;
    @Autowired
    Snowflake snowflake;

    /**
     * 根据用户查询拥有的权限
     * 先查出用户拥有的角色
     * 再去差用户拥有的权限
     * 也可以多表关联查询
     */
    @Override
    public List<SysPermission> getPermission(String userId) {
        List<Integer> roleIds = userRoleService.getRoleIdsByUserId(userId);
        if (roleIds.isEmpty()) {
            return null;
        }
        List<Integer> permissionIds = rolePermissionService.getPermissionIdsByRoles(roleIds);
        if (permissionIds.isEmpty()) {
            return null;
        }
        QueryPermissionReqVo query = new QueryPermissionReqVo();
        List<SysPermission> result = sysPermissionMapper.selectInfoByIds(query, permissionIds);
        return result;
    }


    //根据roleIds查询菜单
    @Override
    public List<SysPermission> getPermissionByRoleIds(List<Integer> roleIds,String lang) {
        List<Integer> permissionIds = rolePermissionService.getPermissionIdsByRoles(roleIds);
        if (permissionIds.isEmpty()) {
            return new ArrayList<>();
        }
        QueryPermissionReqVo query = new QueryPermissionReqVo();
        query.setLang(lang);
        List<SysPermission> result = sysPermissionMapper.selectInfoByIds(query, permissionIds);
        return result;
    }


    @Override
    public List<SysPermission> getPermissionByTop() {
        List<SysPermission> permissions = sysPermissionMapper.selectTopMenu();
        return permissions;
    }

    /**
     * 新增菜单权限
     *
     * @param vo
     * @return com.xh.lesson.entity.SysPermission
     * @throws
     * @CreateDate: 2019/9/20 12:24
     * @UpdateUser:
     * @UpdateDate: 2019/9/20 12:24
     */
    @Override
    public SysPermission addPermission(PermissionAddReqVO vo) {
        SysPermission sysPermission = new SysPermission();
        BeanUtils.copyProperties(vo, sysPermission);
        verifyForm(sysPermission);
        sysPermission.setCreateTime(new Date());
        //通过pid 查询那条数据,判断父级菜单是否为按钮,是则不予新增
        if (!CommonConstant.TOP_PARENT_ID.equals(vo.getPid())) {
            SysPermission permissionValue = sysPermissionMapper.selectByPid(vo.getPid());
            if (CommonConstant.BUTTON_FLAG.equals(permissionValue.getType())) {
                throw new BusinessException(BaseResponseCode.PARENT_NODE_TYPE_NOT_BUTTON);
            }
        }
        //如果是移动端,将url_app icon_app字段赋值
        if (CommonConstant.MenuShowType.APP.equals(vo.getShow())) {
            sysPermission.setUrlApp(vo.getUrl());
            sysPermission.setIconApp(vo.getIcon());
        }

        //当type为菜单时 判断名称是否相同
        if (CommonConstant.MENU_FLAG.equals(vo.getType())) {
            SysPermission selectByName = new SysPermission();
            BeanUtils.copyProperties(vo, selectByName);
            List<SysPermission> permission = sysPermissionMapper.selectByName(selectByName);
            if (!permission.isEmpty()) {
                throw new BusinessException(BaseResponseCode.MENU_NAME_ALREADY_EXISTS_PLEASE_RETYPE);
            }
        }

        //新增菜单按钮时，排序默认赋值为0
        if (CommonConstant.BUTTON_FLAG.equals(vo.getType())) {
            sysPermission.setOrderNum(0);
        } else {
            //查出需要添加的菜单的父节点下的所有菜单，进行排序
            List<SysPermission> permissionRespNodes = sysPermissionMapper.selectChild(vo.getPid());
            Integer orderNum = getAddSort(permissionRespNodes, vo, sysPermission);
            sysPermission.setOrderNum(orderNum);
        }
        int count = sysPermissionMapper.insertSelective(sysPermission);
        if (count != 1) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
        return sysPermission;
    }


    public Integer getAddSort(List<SysPermission> permissionRespNodes, PermissionAddReqVO vo, SysPermission sysPermission) {
        //判断type不为按钮时，返回
        if (vo.getType() != 3) {
            if (vo.getOrderNum() == null) {
                throw new BusinessException(BaseResponseCode.MENU_TYPE_NOT_BUTTON_PLEASE_ADD_ORDER_NUM);
            } else {
                //目标值
                Integer orderNum = vo.getOrderNum();
                if (orderNum <= CommonConstant.ONE) {
                    orderNum = CommonConstant.ONE;
                }
                if (orderNum > permissionRespNodes.size()) {
                    orderNum = permissionRespNodes.size() + 1;
                } else {
                    for (SysPermission permission : permissionRespNodes) {
                        if (permission.getOrderNum() >= orderNum) {
                            SysPermission syspermission = new SysPermission();
                            syspermission.setId(permission.getId());
                            syspermission.setOrderNum(permission.getOrderNum() + 1);
                            sysPermissionMapper.updateByPrimaryKeySelective(syspermission);
                        }
                    }
                }
                return orderNum;
            }
        }
        return CommonConstant.ZERO;
    }


    /**
     * 操作后的菜单类型是目录的时候 父级必须为目录
     * 操作后的菜单类型是菜单的时候，父类必须为目录类型
     * 操作后的菜单类型是按钮的时候 父类必须为菜单类型
     */
    private void verifyFormPid(SysPermission sysPermission) {
        SysPermission parent = selectByPrimaryKey(sysPermission.getPid());
        switch (sysPermission.getType()) {
            case 1:
                if (parent != null) {
                    if (parent.getType() != 1) {
                        throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR);
                    }
                } else if (!sysPermission.getPid().equals(CommonConstant.TOP_PARENT_ID)) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_CATALOG_ERROR);
                }
                break;
            case 2:
                //只保留菜单
                /*if (parent == null || parent.getType() != 1) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_MENU_ERROR);
                }*/
                if (StringUtils.isEmpty(sysPermission.getUrl())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
                }
                sysPermission.setPerms(null);
                break;
            case 3:
                if (parent == null || parent.getType() != 2) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_BTN_ERROR);
                }
                if (StringUtils.isEmpty(sysPermission.getPerms())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_PERMS_NULL);
                }
                /*if (StringUtils.isEmpty(sysPermission.getUrl())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_NOT_NULL);
                }
                if (StringUtils.isEmpty(sysPermission.getMethod())) {
                    throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_URL_METHOD_NULL);
                }*/
                break;
            default:
                break;
        }
    }

    /**
     * 编辑或者新增的时候检验
     *
     * @param sysPermission
     * @return void
     * @throws
     * @CreateDate: 2019/10/31 21:22
     * @UpdateUser:
     * @UpdateDate: 2019/10/31 21:22
     */
    private void verifyForm(SysPermission sysPermission) {

        verifyFormPid(sysPermission);
        /**
         * id 不为空说明是编辑
         */
        if (!StringUtils.isEmpty(sysPermission.getId())) {
            List<SysPermission> list = sysPermissionMapper.selectChild(sysPermission.getId());
            if (!list.isEmpty()) {
                throw new BusinessException(BaseResponseCode.OPERATION_MENU_PERMISSION_UPDATE);
            }
        }

    }

    /**
     * 查询菜单权限详情
     *
     * @param permissionId
     * @return com.xh.lesson.entity.SysPermission
     * @throws
     * @Author: fancl
     * @CreateDate: 2022/8/10
     * @UpdateUser:
     * @UpdateDate: 2022/8/10
     */
    @Override
    public SysPermission detailInfo(Integer permissionId) {
        //根据菜单Id查询关联表
        List<PermStationRelation> permStationRelations = permStationRelationService.selectByPermissionId(permissionId);
        List<Integer> collect = permStationRelations.stream().map(s -> {
                    return s.getStationId();
                }
        ).collect(Collectors.toList());

        SysPermission sysPermission = selectByPrimaryKey(permissionId);
        sysPermission.setStationList(collect);
        return sysPermission;
    }

    //查询 系统管理 这条记录
    @Override
    public SysPermission findSysManageMenu() {
        SysPermission sysPermissionQuery = new SysPermission();
        //sysPermissionQuery.setName(CommonConstant.SYS_MENU_NAME);
        //sysPermissionQuery.setPid(CommonConstant.TOP_PARENT_ID);
        sysPermissionQuery.setId(CommonConstant.SYS_MENU_Id);
        SysPermission sysPermission = sysPermissionMapper.selectOneByCondition(sysPermissionQuery);
        return sysPermission;
    }

    //查询 name是menu 这条记录
    @Override
    public SysPermission findTheMenu() {
        SysPermission sysPermissionQuery = new SysPermission();
        ///sysPermissionQuery.setName(CommonConstant.PERMISSION_MENU_NAME);
        sysPermissionQuery.setId(CommonConstant.PERMISSION_MENU_ID);
        SysPermission sysPermission = sysPermissionMapper.selectOneByCondition(sysPermissionQuery);
        return sysPermission;
    }

    /**
     * 更新菜单权限
     */
    @Override
    public void updatePermission(PermissionUpdateReqVO vo) {
        SysPermission sysPermission = selectByPrimaryKey(vo.getId());
        if (null == sysPermission) {
            log.error("传入 的 id:{}不合法", vo.getId());
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        if (CommonConstant.DELETED_FLAG.equals(sysPermission.getDeleted())) {
            log.info("传入 的 id:{}已经被删除,不需要排序", vo.getId());
            throw new BusinessException(BaseResponseCode.DATA_NOT_EXISTS);
        }

        //判断要更新的数据 的原数据是否为type是否为菜单类型 与更新的数据中的type进行比较
        //原数据为菜单类型则不能更改为按钮类型
        if (CommonConstant.BUTTON_FLAG.equals(vo.getType())) {
            //原数据的pid等于0（一级菜单），则不能修改
            if (CommonConstant.TOP_PARENT_ID.equals(sysPermission.getPid())) {
                //类型为菜单的数据不能更改为按钮类型
                throw new BusinessException(BaseResponseCode.PRIMARY_MENU_CANNOT_MODIFIED_TYPE_BUTTON);
            }
            //原数据下面有子级的不能修改
            //根据 id=pid查询 才能查到所修改的数据下的子级
            List<SysPermission> sysPermissions = sysPermissionMapper.selectChild(vo.getId());
            if (sysPermissions.size() != CommonConstant.ZERO) {
                throw new BusinessException(BaseResponseCode.MENU_SUB_LEVEL_ASSOCIATED_DATA_CANNOT_MODIFIED);
            }

            if (sysPermission.getUrl() != null) {
                vo.setUrl("");
            }
            if (sysPermission.getOrderNum() != null) {
                vo.setOrderNum(null);
            }
            if (sysPermission.getIcon() != null) {
                vo.setIcon("");
            }
            if (sysPermission.getShow() != null) {
                vo.setShow("");
            }
        } else {
            if (sysPermission.getPerms() != null) {
                vo.setPerms("");
            }
        }

        //是否有其他Id的perms相同
        if (!StrUtil.isBlank(vo.getPerms())) {
            SysPermission sysPerm = sysPermissionMapper.selectOtherByIdAndPerms(vo.getId(), vo.getPerms());
            if (sysPerm != null) {
                throw new BusinessException(BaseResponseCode.PERMISSION_ALREADY_EXISTS);
            }
        }

        //当type为菜单时 判断名称是否相同 加id条件，在更新时不查到自己本身
        if (CommonConstant.MENU_FLAG.equals(vo.getType())) {
            SysPermission selectByName = new SysPermission();
            BeanUtils.copyProperties(vo, selectByName);
            List<SysPermission> permission = sysPermissionMapper.selectByName(selectByName);
            if (!permission.isEmpty()) {
                throw new BusinessException(BaseResponseCode.MENU_NAME_ALREADY_EXISTS_PLEASE_RETYPE);
            }
        }

        SysPermission selectByPid = new SysPermission();
        //如果不是顶级节点
        if (!CommonConstant.TOP_PARENT_ID.equals(vo.getPid())) {
            selectByPid = selectByPrimaryKey(vo.getPid());
            //如果是删除状态
            if (CommonConstant.DELETED_FLAG.equals(selectByPid.getDeleted())) {
                throw new BusinessException(BaseResponseCode.PARENT_MENU_DELENTION_STATUS);
            }
            //如果是未启用状态
            if (CommonConstant.ZERO.equals(selectByPid.getStatus())) {
                throw new BusinessException(BaseResponseCode.PARENT_MENU_NOT_UPDATE_ENABLED);
            }
        }
        SysPermission update = new SysPermission();
        BeanUtils.copyProperties(vo, update);
        //如果是移动端,将url_app icon_app字段赋值
        if (CommonConstant.MenuShowType.APP.equals(vo.getShow())) {
            update.setUrlApp(vo.getUrl());
            update.setIconApp(vo.getIcon());
        }
        /**
         * 只有类型变更
         * 或者所属菜单变更
         */
        //因为不直接变更层级,所以即使菜单下有
        /*if (sysPermission.getType() != vo.getType() || !sysPermission.getPid().equals(vo.getPid())) {
            verifyForm(update);
        }*/

        //查出需要更改的菜单的父节点下的的菜单，进行排序
        List<SysPermission> permissionRespNodes = sysPermissionMapper.selectChild(vo.getPid());
        Integer updateSort = getUpdateSort(permissionRespNodes, vo, sysPermission);
        update.setOrderNum(updateSort);

        update.setUpdateTime(new Date());
        int count = updateByPrimaryKeySelective(update);
        if (count != 1) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
        /**
         * 说明这个菜单权限 权鉴标识发生变化
         * 所有管理这个菜单权限用户将重新刷新token
         */
        if (!StringUtils.isEmpty(vo.getPerms()) && !vo.getPerms().equals(sysPermission.getPerms())) {
            List<Integer> roleIds = rolePermissionService.getRoleIds(vo.getId());
            //清空角色对应的用户缓存
            if (roleIds != null && !roleIds.isEmpty()) {
                //删除角色对应用户缓存
                try {
                    redisUpdateService.cleanLoginInfosByRoleId(roleIds);
                } catch (Exception e) {
                    log.error("删除菜单权限 删除和角色关联 清除缓存报错:" + e.getMessage());
                }
            }
            /*if (!roleIds.isEmpty()) {
                List<String> userIds = userRoleService.getUserIdsByRoleIds(roleIds);
                if (!userIds.isEmpty()) {
                    for (String userId : userIds) {

                        //    redisService.set(Constant.JWT_REFRESH_KEY + userId, userId, tokenSettings.getAccessTokenExpireTime().toMillis(), TimeUnit.MILLISECONDS);
                        //清空权鉴缓存
                        redisService.delete(RedisKeyConstant.User.IDENTIFY_CACHE_KEY + userId);
                    }
                }
            }*/
        }
        /**
         * 修改状态时需要修改子集相关的状态
         */
        if (vo.getStatus() != null) {

            Integer status = vo.getStatus();
            //查询到父级菜单
            SysPermission permission = selectByPrimaryKey(vo.getId());
            //启用
            if (status == 1) {
                //判断父级菜单的状态
                if (permission.getStatus() != 1) {
                    throw new BusinessException(BaseResponseCode.PARENT_PERMISSION_IS_DISABLE);
                }
            }
            //禁用
            else {
                //禁用菜单就修改禁用该菜单及以下子部门
                List<Integer> ids = new ArrayList<>();
                ids.add(permission.getId());
                List<SysPermission> childAll = getSysMangeMenus(new ArrayList<>(), ids);

                childAll.stream().filter(s -> {
                    //按钮不能禁用
                    return !CommonConstant.BUTTON_FLAG.equals(s.getType());
                }).map(s -> {
                    return s.getId();
                }).forEach(s -> {
                    SysPermission permissionValue = selectByPrimaryKey(s);
                    SysPermission child = new SysPermission();
                    child.setId(s);
                    child.setStatus(0);
                    child.setOrderNum(permissionValue.getOrderNum());
                    sysPermissionMapper.updateByPrimaryKeySelective(child);


                });
            }
        }

    }


    public Integer getUpdateSort(List<SysPermission> permissionRespNodes, PermissionUpdateReqVO vo, SysPermission sysPermission) {
        //判断type不为按钮时，返回
        if (vo.getType() != 3) {
            if (vo.getOrderNum() == null) {
                throw new BusinessException(BaseResponseCode.MENU_TYPE_NOT_BUTTON_PLEASE_ADD_ORDER_NUM);
            } else {
                //这个记录原来的排序数值
                Integer origNum = sysPermission.getOrderNum();
                //这次要改为的值
                Integer targetOrderNum = vo.getOrderNum();
                if (targetOrderNum <= CommonConstant.ONE) {
                    targetOrderNum = CommonConstant.ONE;
                }
                if (targetOrderNum > permissionRespNodes.size()) {
                    targetOrderNum = permissionRespNodes.size();
                }
                for (SysPermission permissionRespNode : permissionRespNodes) {
                    //从大往小移动 别的值如果>=orderNumNow,并且小于原始值 , 这个值+1
                    if (permissionRespNode.getOrderNum() >= targetOrderNum && permissionRespNode.getOrderNum() < origNum
                            && !permissionRespNode.getId().equals(sysPermission.getId())) {
                        SysPermission syspermission = new SysPermission();
                        syspermission.setId(permissionRespNode.getId());
                        syspermission.setOrderNum(permissionRespNode.getOrderNum() + 1);
                        updateByPrimaryKeySelective(syspermission);
                    }
                    //从小往大移动 别的值如果>原始值 ,<= orderNumNow这个值-1
                    if (permissionRespNode.getOrderNum() > origNum && permissionRespNode.getOrderNum() <= targetOrderNum
                            && !permissionRespNode.getId().equals(sysPermission.getId())) {
                        SysPermission syspermission = new SysPermission();
                        syspermission.setId(permissionRespNode.getId());
                        syspermission.setOrderNum(permissionRespNode.getOrderNum() - 1);
                        updateByPrimaryKeySelective(syspermission);
                    }
                }
                return targetOrderNum;
            }

        }
        return CommonConstant.ZERO;
    }


    @Override
    public Integer updateByPrimaryKeySelective(SysPermission sysPermission) {
        int count = sysPermissionMapper.updateByPrimaryKeySelective(sysPermission);
        return count;
    }

    /**
     * 删除菜单权限
     * 判断是否 有角色关联
     * 判断是否有子集
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleted(Integer permissionId) {
        //根据id查询
        SysPermission sysPermission = selectByPrimaryKey(permissionId);
        if (CommonConstant.ONE.equals(sysPermission.getStatus()) && !CommonConstant.BUTTON_FLAG.equals(sysPermission.getType())) {
            throw new BusinessException(BaseResponseCode.MENU_CANNOT_NOT_STATE_DELETE);
        }
        if (null == sysPermission) {
            log.error("传入 的 id:{}不合法", permissionId);
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        List<SysPermission> childs = sysPermissionMapper.selectChild(permissionId);
        if (!childs.isEmpty()) {
            throw new BusinessException(BaseResponseCode.ROLE_PERMISSION_RELATION);
        }
        sysPermission.setDeleted(0);
        sysPermission.setUpdateTime(new Date());

        //查出要删除的菜单的父节点下的所有菜单，进行排序
        List<SysPermission> permissionRespNodes = sysPermissionMapper.selectChild(sysPermission.getPid());
        //删除后补齐
        for (SysPermission permission : permissionRespNodes) {
            if (permission.getOrderNum() > sysPermission.getOrderNum()) {
                SysPermission syspermission = new SysPermission();
                syspermission.setId(permission.getId());
                syspermission.setOrderNum(permission.getOrderNum() - 1);
                updateByPrimaryKeySelective(syspermission);
            }
        }
        int count = updateByPrimaryKeySelective(sysPermission);
        if (count != 1) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
        /**
         * 删除和角色关联
         */
        rolePermissionService.removeByPermissionId(permissionId);
        List<Integer> roleIds = rolePermissionService.getRoleIds(permissionId);
        if (roleIds != null && !roleIds.isEmpty()) {
            //删除角色对应用户缓存
            try {
                redisUpdateService.cleanLoginInfosByRoleId(roleIds);
            } catch (Exception e) {
                log.error("删除菜单权限 删除和角色关联 清除缓存报错:" + e.getMessage());
            }
        }

        /*if (!roleIds.isEmpty()) {
            List<String> userIds = userRoleService.getUserIdsByRoleIds(roleIds);

            if (!userIds.isEmpty()) {
                for (String userId : userIds) {
                  //  redisService.set(Constant.JWT_REFRESH_KEY + userId, userId, tokenSettings.getAccessTokenExpireTime().toMillis(), TimeUnit.MILLISECONDS);
                    //更新缓存
                    UserDetailRespVO userDetail = userService.getUserDetail(userId);
                    SysUser user = userService.getUserByName(userDetail.getUsername());
                    redisUpdateService.updateRedis(userDetail,user);
                    //清空权鉴缓存
                    redisService.delete(RedisKeyConstant.User.IDENTIFY_CACHE_KEY + userId);
                }

            }
        }*/
    }


    /**
     * 分页获取所有菜单权限
     */
    @Override
    public PageVO<SysPermission> pageInfo(PermissionPageReqVO vo) {

        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        QueryPermissionReqVo query = new QueryPermissionReqVo();
        List<SysPermission> list = selectAll(query, null, null);
        return PageUtilsOld.getPageVO(list);
    }


    /**
     * 获取所有菜单权限
     * 超管可以查询到全部菜单, 非超管只能查询到角色关联菜单
     * 具有菜单维护权限的人员也可以查询到全部菜单
     *
     * @param
     * @return java.util.List<com.xh.lesson.entity.SysPermission>
     * @throws
     * @Author:
     * @CreateDate: 2019/9/20 14:03
     * @UpdateUser:
     * @UpdateDate: 2019/9/20 14:03
     * @Version: 0.0.1
     */
    @Override
    public List<SysPermission> selectAll(QueryPermissionReqVo query, String enableStatus, String enableType) {
        SimpleUser simpleUser = getCurrentSimpleUser();
        List<SysPermission> result = new ArrayList<>();
        //如果是超管,选择全部菜单,如果不是超管,使用权限管理的菜单
        if (simpleUser.getPlatSuper()) {
            result = sysPermissionMapper.selectAll(query, enableStatus, enableType);
        } else {
            //这个人是否有菜单管理权限
            SysPermission theMenu = findTheMenu();
            List<Integer> roleIdsByUserId = userRoleService.getRoleIdsByUserId(simpleUser.getUserId());
            List<Integer> permissionIdsByRoleId = rolePermissionService.getPermissionIdsByRoles(roleIdsByUserId);
            //如果有菜单管理权限,就查询全部菜单
            if (permissionIdsByRoleId != null && permissionIdsByRoleId.contains(theMenu.getId())) {
                log.info("这个人具备系统菜单管理权限: userId:{} " + simpleUser.getUserId());
                result = sysPermissionMapper.selectAll(query, enableStatus, enableType);
            } else {
                result = sysPermissionMapper.selectInfoByIds(query, permissionIdsByRoleId);
            }
        }

        //List<SysPermission> result = sysPermissionMapper.selectAll();
        //因为所有数据已经查出来了,只需把parentName遍历一遍赋值

        /*if (!result.isEmpty()) {
            for (SysPermission sysPermission : result) {
                SysPermission parent = selectByPrimaryKey(sysPermission.getPid());
                if (parent != null) {
                    sysPermission.setPidName(parent.getName());
                }
            }
        }*/
        for (SysPermission sysPermission : result) {
            //顶级的不用赋值
            if (sysPermission.getPid().equals(CommonConstant.TOP_PARENT_ID)) {
                continue;
            }
            //找到pid的那条记录
            for (SysPermission permission : result) {
                if (sysPermission.getPid().equals(permission.getId())) {
                    sysPermission.setPidName(permission.getName());
                }
            }
        }
        return result;
    }

    @Override
    public SysPermission selectByPerms(String perms) {
        SysPermission sysPermission = sysPermissionMapper.selectByPerms(perms);
        return sysPermission;
    }

    /**
     * 获取权限标识
     *
     * @param userId
     * @return java.util.List<java.lang.String>
     * @throws
     * @Author:
     * @CreateDate: 2019/9/20 23:13
     * @UpdateUser:
     * @UpdateDate: 2019/9/20 23:13
     * @Version: 0.0.1
     */
    @Override
    public Set<String> getPermissionsByUserId(String userId) {

        List<SysPermission> list = getPermission(userId);
        Set<String> permissions = new HashSet<>();
        if (null == list || list.isEmpty()) {
            return null;
        }
        for (SysPermission sysPermission : list) {
            if (!StringUtils.isEmpty(sysPermission.getPerms())) {
                permissions.add(sysPermission.getPerms());
            }

        }
        return permissions;
    }

    /**
     * 以树型的形式把用户拥有的菜单权限返回给客户端
     *
     * @param userId
     * @return java.util.List<com.xh.lesson.vo.resp.PermissionRespNode>
     * @throws
     * @Author:
     * @CreateDate: 2019/9/23 10:53
     * @UpdateUser:
     * @UpdateDate: 2019/9/23 10:53
     * @Version: 0.0.1
     */
    @Override
    public List<PermissionRespNode> permissionTreeList(String userId) {
        List<SysPermission> list = getPermission(userId);
        return getTree(list, true);
    }

    /**
     * 递归获取菜单树
     * 这个地方后续得改造为区分系统管理员(可以查看所有集团)
     * 每个集团管理员仅可以管理集团下的机构
     *
     * @param all
     * @param type true:查询到菜单；false:查询到按钮
     * @return java.util.List<com.xh.lesson.vo.resp.PermissionRespNode>
     * @throws
     * @Author:
     * @CreateDate: 2019/10/27 18:27
     * @UpdateUser:
     * @UpdateDate: 2019/10/27 18:27
     * @Version: 0.0.1
     */
    private List<PermissionRespNode> getTree(List<SysPermission> all, boolean type) {

        List<PermissionRespNode> list = new ArrayList<>();
        List<PermissionRespNode> PermissionRespNodeList = new ArrayList<>();
        if (all == null || all.isEmpty()) {
            return list;
        }
        for (SysPermission sysPermission : all) {
            if (CommonConstant.TOP_PARENT_ID.equals(sysPermission.getPid())) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setName(sysPermission.getName());

                if (type) {
                    permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                } else {
                    permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                }
                list.add(permissionRespNode);
            }
        }

        //如果返回的list为空，则说明查出来的所有菜单没有父级菜单，则平铺返回
        if (list.isEmpty() || list.size() == 0) {
            for (SysPermission sysPermission : all) {
                SysPermission date = sysPermissionMapper.selectByPid(sysPermission.getPid());
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setName(sysPermission.getName());
                permissionRespNode.setPidName(date.getName());
                list.add(permissionRespNode);
            }
        }

        //按照orderNum排序
        List<PermissionRespNode> sortedList = new ArrayList<>();

        //找没有父亲的数据
        List<PermissionRespNode> noFatherDatas = findNoFatherDatas(all);
        if (noFatherDatas.size() != (all.size())) {
            list.addAll(noFatherDatas);
            //按照orderNum排序
            sortedList = list.stream().sorted(Comparator.comparing(PermissionRespNode::getOrderNum)).collect(Collectors.toList());
        } else {
            PermissionRespNodeList.addAll(list);
            //按照orderNum排序
            sortedList = PermissionRespNodeList.stream().sorted(Comparator.comparing(PermissionRespNode::getOrderNum)).collect(Collectors.toList());
        }

        return sortedList.stream().collect(Collectors.toList());
    }

    private List<PermissionRespNode> getPermissionTree(List<SysPermission> all, boolean type) {
        List<PermissionRespNode> list = new ArrayList<>();
        if (all == null || all.isEmpty()) {
            return list;
        }
        for (SysPermission sysPermission : all) {
            //
            if (CommonConstant.TOP_PARENT_ID.equals(sysPermission.getPid())) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setName(sysPermission.getName());
                if (type) {
                    permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                } else {
                    permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                }
                list.add(permissionRespNode);
            } else {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setName(sysPermission.getName());
                if (type) {
                    permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                } else {
                    permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                }
                list.add(permissionRespNode);
            }
        }
        //按照orderNum排序
        List<PermissionRespNode> sortedList = list.stream().sorted(Comparator.comparing(PermissionRespNode::getOrderNum)).collect(Collectors.toList());
        return sortedList.stream().collect(Collectors.toList());
    }

    private List<PermissionRespNode> findNoFatherDatas(List<SysPermission> inputList) {
        List<PermissionRespNode> list = new ArrayList<>();
        for (SysPermission node : inputList) {
            boolean hasFather = false;
            for (SysPermission fatherNode : inputList) {
                //这种是有父亲的
                if (node.getPid().equals(fatherNode.getId()) || CommonConstant.ZERO.equals(node.getPid())) {
                    hasFather = true;
                    break;
                }
            }
            //没有父亲的，加进来
            if (!hasFather) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(node, permissionRespNode);
                permissionRespNode.setTitle(node.getName());
                permissionRespNode.setPidName(node.getName());
                list.add(permissionRespNode);
            }
        }
        for (PermissionRespNode permissionRespNode : list) {
            SysPermission date = sysPermissionMapper.selectByPid(permissionRespNode.getPid());
            permissionRespNode.setPidName(date.getName());
        }
        return list;
    }

    /**
     * 递归遍历所有
     *
     * @param id
     * @param all
     * @return java.util.List<com.xh.lesson.vo.resp.PermissionRespNode>
     * @throws
     * @Author:
     * @CreateDate: 2019/10/25 16:51
     * @UpdateUser:
     * @UpdateDate: 2019/10/25 16:51
     * @Version: 0.0.1
     */
    private List<PermissionRespNode> getChildAll(Integer id, List<SysPermission> all) {
        List<PermissionRespNode> list = new ArrayList<>();
        for (SysPermission sysPermission : all) {
            if (sysPermission.getPid().equals(id)) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setName(sysPermission.getName());
                permissionRespNode.setChildren(getChildAll(sysPermission.getId(), all));
                list.add(permissionRespNode);
            }
        }
        //按照orderNum排序
        List<PermissionRespNode> sortedList = list.stream().sorted(Comparator.comparing(PermissionRespNode::getOrderNum)).collect(Collectors.toList());
        return sortedList;
    }

    /**
     * 只递归获取目录和菜单
     */
    private List<PermissionRespNode> getChildExcBtn(Integer id, List<SysPermission> all) {

        List<PermissionRespNode> list = new ArrayList<>();
        for (SysPermission sysPermission : all) {
            if (sysPermission.getPid().equals(id) && CommonConstant.BUTTON_FLAG.equals(sysPermission.getType())) {
                PermissionRespNode permissionRespNode = new PermissionRespNode();
                BeanUtils.copyProperties(sysPermission, permissionRespNode);
                permissionRespNode.setTitle(sysPermission.getName());
                permissionRespNode.setName(sysPermission.getName());
                permissionRespNode.setChildren(getChildExcBtn(sysPermission.getId(), all));
                list.add(permissionRespNode);
            }
        }
        return list;
    }

    /**
     * 菜单组树结构
     */
    public List<PermissionRespNode> getByTree(List<SysPermission> list) {
        //判断数据中有子级的数据的pid是否全为0
        //找到所有有孩子的数据，在判断这些数据pid是否全为0
        List<SysPermission> fatherList = new ArrayList<>();
        //是儿子的数据集
        Map<Integer, SysPermission> sunMap = new HashMap<>();
        for (SysPermission dept : list) {
            for (SysPermission father : list) {
                if (dept.getPid().equals(father.getId())) {
                    sunMap.put(dept.getId(), dept);
                    break;
                }
            }
        }
        //不是儿子的就是祖宗（查到的数据的最顶级）
        for (SysPermission dept : list) {
            if (!sunMap.containsKey(dept.getId())) {
                fatherList.add(dept);
            }
        }

        //判断fatherList中的pid是否全部等于0
        boolean isTopId = true;
        for (SysPermission dept : fatherList) {
            if (!CommonConstant.TOP_PARENT_ID.equals(dept.getPid())) {
                isTopId = false;
                break;
            }
        }
        List<PermissionRespNode> tree = new ArrayList<>();
        //全部的顶级数据pid = 0 时 走getTree
        if (isTopId) {
            tree = getTree(list, false);
        } else {
            List<PermissionRespNode> permissionTree = getPermissionTree(list, false);
            for (PermissionRespNode permissionRespNode : permissionTree) {
                if (!sunMap.containsKey(permissionRespNode.getId())) {
                    tree.add(permissionRespNode);
                }
            }

        }
        //为返回数据查询父级名称
        for (PermissionRespNode permissionRespNode : tree) {
            if (permissionRespNode.getPid().equals(CommonConstant.TOP_PARENT_ID)) {
                permissionRespNode.setPidName(null);
            } else {
                SysPermission sysPermission = sysPermissionMapper.selectByPid(permissionRespNode.getPid());
                permissionRespNode.setPidName(sysPermission.getName());
            }
        }
        return tree;
    }


    /**
     * 获取所有菜单权限按钮
     */
    @Override
    public List<PermissionRespNode> selectAllByTree(QueryPermissionReqVo query, String enableStatus, String enableType) {

        List<SysPermission> list = selectAll(query, enableStatus, enableType);
        List<PermissionRespNode> tree = getByTree(list);
        return tree;
    }

    public List<PermissionRespNode> getTree(List<SysPermission> list) {
        //判断数据中有子级的数据的pid是否全为0
        //找到所有有孩子的数据，在判断这些数据pid是否全为0
        List<SysPermission> fatherList = new ArrayList<>();
        //是儿子的数据集
        Map<Integer, SysPermission> sunMap = new HashMap<>();
        for (SysPermission dept : list) {
            for (SysPermission father : list) {
                if (dept.getPid().equals(father.getId())) {
                    sunMap.put(dept.getId(), dept);
                    break;
                }
            }
        }
        //不是儿子的就是祖宗（查到的数据的最顶级）
        for (SysPermission dept : list) {
            if (!sunMap.containsKey(dept.getId())) {
                fatherList.add(dept);
            }
        }

        //判断fatherList中的pid是否全部等于0
        boolean isTopId = true;
        for (SysPermission dept : fatherList) {
            if (!CommonConstant.TOP_PARENT_ID.equals(dept.getPid())) {
                isTopId = false;
                break;
            }
        }
        List<PermissionRespNode> tree = new ArrayList<>();
        //全部的顶级数据pid = 0 时 走getTree
        if (isTopId) {
            tree = getTree(list, false);
        } else {
            List<PermissionRespNode> permissionTree = getPermissionTree(list, false);
            for (PermissionRespNode permissionRespNode : permissionTree) {
                if (!sunMap.containsKey(permissionRespNode.getId())) {
                    tree.add(permissionRespNode);
                }
            }

        }
        //为返回数据查询父级名称
        for (PermissionRespNode permissionRespNode : tree) {
            if (permissionRespNode.getPid().equals(CommonConstant.TOP_PARENT_ID)) {
                permissionRespNode.setPidName(null);
            } else {
                SysPermission sysPermission = sysPermissionMapper.selectByPid(permissionRespNode.getPid());
                permissionRespNode.setPidName(sysPermission.getName());
            }
        }
        return tree;
    }

    /**
     * 获取所有启用的菜单权限按钮
     * @return
     */
//    @Override
//    public List<PermissionRespNode> selectAllByStatus() {
//        List<SysPermission> sysPermissions = sysPermissionMapper.selectAllByStatus();
//        return sysPermissions;
//    }


    /**
     * 根据pid查询删除状态
     *
     * @return
     */
    @Override
    public SysPermission selectByPrimaryKey(Integer pid) {
        SysPermission sysPermission = sysPermissionMapper.selectByPrimaryKey(pid);
        return sysPermission;
    }


    /**
     * 获取所有的目录菜单树排除按钮
     * 因为不管是新增或者修改
     * 选择所属菜单目录的时候
     * 都不可能选择到按钮
     * 而且编辑的时候 所属目录不能
     * 选择自己和它的子类
     */
//    @Override
//    public List<PermissionRespNode> selectAllMenuByTree(Integer permissionId) {
//        //所有菜单
//        List<SysPermission> list = selectAll();
//        if (!list.isEmpty() && !StringUtils.isEmpty(permissionId)) {
//            for (SysPermission sysPermission : list) {
//                if (sysPermission.getId().equals(permissionId)) {
//                    list.remove(sysPermission);
//                    break;
//                }
//            }
//        }
//        List<PermissionRespNode> result = new ArrayList<>();
//        //新增顶级目录是为了方便添加一级目录
//        PermissionRespNode respNode = new PermissionRespNode();
//        respNode.setId(CommonConstant.TOP_PARENT_ID);
//        respNode.setTitle("默认顶级菜单");
//        respNode.setSpread(true);
//        respNode.setChildren(getTree(list, true));
//        result.add(respNode);
//        //List<PermissionRespNode> result = getTree(list, true);
//
//        return result;
//    }
    @Override
    public SimpleUser getCurrentSimpleUser() {
        //非 超级管理员 ,查询到的菜单树应该是根据角色关联的
        Subject subject = SecurityUtils.getSubject();
        String accessToken = (String) subject.getPrincipal();
        UserDetailRespVO userDetailRespVO = (UserDetailRespVO) redisService.get(RedisKeyConstant.User.TOKEN + accessToken);
        String userNameKey = redisService.getUserNameKey(userDetailRespVO, userDetailRespVO.getUsername());
        SimpleUser simpleUser = (SimpleUser) redisService.get(userNameKey);
        return simpleUser;
    }

    @Override
    public List<SysPermission> getSysMangeMenus(List<SysPermission> list, List<Integer> queryIds) {
        if (queryIds == null || queryIds.isEmpty()) {
            return list;
        }
        //查询父id在queryIds中的
        List<SysPermission> sysPermissions = sysPermissionMapper.selectChilds(queryIds);
        List<Integer> ids = new ArrayList<>();
        list.addAll(sysPermissions);
        //将ids作为下一次循环的入参
        for (SysPermission sysPermission : sysPermissions) {
            ids.add(sysPermission.getId());
        }
        return getSysMangeMenus(list, ids);
    }

    @Override
    public List<PermissionRespNode> getStationPer(Integer stationId, UserDetailRespVO user,String lang) {
        List<SysPermission> list = new ArrayList<>();
        //查询当前登录人所拥有的菜单
        List<Integer> roleIds = user.getRoleIds();
        List<SysPermission> userPermissions = new ArrayList<>();
        if (!roleIds.isEmpty()) {
            //到关联表中根据角色id 拿到对应的菜单id
            List<SysPermission> result = getPermissionByRoleIds(roleIds,lang);
            List<Integer> perIds = result.stream().map(s -> {
                        return s.getId();
                    }
            ).collect(Collectors.toList());
            // List<Integer> permissionIdsByRoles = rolePermissionService.getPermissionIdsByRoles(roleIds);
            //根据菜单Id拿到菜单列表
            List<SysPermission> sysPermissions = selectByIds(perIds,lang);
            //过滤掉按钮类型的数据
            userPermissions = sysPermissions.stream().filter(s -> !s.getType().equals(CommonConstant.THREE)).collect(Collectors.toList());
        }
        //根据电站查询关联表，
        List<PermStationRelation> permStationRelations = permStationRelationService.selectByStationId(stationId);
        List<SysPermission> permissions = new ArrayList<>();
        //根据关联表中的菜单Id进行查单查询
        List<Integer> perIds = permStationRelations.stream().map(s -> {
                    return s.getPermissionId();
                }
        ).collect(Collectors.toList());
        if (!perIds.isEmpty()) {
            permissions = selectByIds(perIds,lang);
        }
        if (permissions.isEmpty()) {
            list = userPermissions;
        } else if (userPermissions != null && permissions != null) {
            for (SysPermission userPermission : userPermissions) {
                for (SysPermission permission : permissions) {
                    if (userPermission.getId().equals(permission.getId())) {
                        list.add(userPermission);
                    }
                }
            }
        } else {
            list = new ArrayList<>();
        }
        //再根据查询全部菜单时，查询公共的菜单(隐藏)
        //List<SysPermission> sysPermissions = sysPermissionMapper.selectByScope();
        // list.addAll(sysPermissions);
        //将两个结果进行合并
        //对返回数据进行组装返回
        List<PermissionRespNode> tree = getTree(list);
        return tree;
    }

    @Override
    public List<PermissionRespNode> getAll(QueryPermissionReqVo query) {
        List<SysPermission> sysPermissions = sysPermissionMapper.selectAll(query, null, "enableType");
        List<PermissionRespNode> tree = getByTree(sysPermissions);
        return tree;
    }

    private List<SysPermission> selectByIds(List<Integer> perIds,String lang){
        List<SysPermission> sysPermissions = sysPermissionMapper.selectByIds(perIds,lang);
        return sysPermissions;
    }
}
