package com.ho.user.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.github.pagehelper.PageHelper;
import com.ho.common.tools.constant.CommonConstant;
import com.ho.common.tools.entity.PageVO;
import com.ho.common.tools.entity.SysPermission;
import com.ho.common.tools.entity.SysRole;
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.CodeUtil;
import com.ho.common.tools.util.PageUtilsOld;
import com.ho.user.api.entity.SysDept;
import com.ho.user.api.vo.req.QueryPermissionReqVo;
import com.ho.user.entity.IdControl;
import com.ho.user.entity.PermissionRespNode;
import com.ho.user.mapper.SysRoleMapper;
import com.ho.user.mapper.SysUserRoleMapper;
import com.ho.user.service.*;
import com.ho.user.util.TokenSettings;
import com.ho.user.vo.req.RoleAddReqVO;
import com.ho.user.vo.req.RolePageReqVO;
import com.ho.user.vo.req.RolePermissionOperationReqVO;
import com.ho.user.vo.req.RoleUpdateReqVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.checkerframework.checker.units.qual.A;
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 java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
public class RoleServiceImpl implements RoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RolePermissionService rolePermissionService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private RedisUpdateService redisUpdateService;
    @Autowired
    private TokenSettings tokenSettings;
    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;
    @Autowired
    private PermissionService permissionService;
    @Autowired
    @Lazy
    private UserService userService;

    @Autowired
    private Snowflake snowflake;

    @Autowired
    private IdControlService idControlService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysRole addRole(RoleAddReqVO vo) {
        //相同角色名不能相同
        RolePageReqVO query = new RolePageReqVO();
        query.setRoleName(vo.getName());
        List<SysRole> sysRoles = sysRoleMapper.selectListByCondition(query);
        if (!sysRoles.isEmpty()) {
            throw new BusinessException(BaseResponseCode.ROLE_NAME_ALREADY_EXITS);
        }
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(vo, sysRole);
        //生成一个随机的角色编号
        IdControl idControl = idControlService.selectCurrentVal(CommonConstant.ROLE_KEY);
        IdControl control = null;
        Integer currentVal = null;
        if (idControl == null) {
            control = new IdControl();
            control.setType(CommonConstant.ROLE_KEY);
            control.setCurrentVal(0);
            Integer insert = idControlService.insert(control);
            currentVal = control.getCurrentVal();
        } else {
            currentVal = idControl.getCurrentVal();
        }
        Integer result = ++currentVal;
        String roleCode = CodeUtil.getCode(CodeUtil.AUTO_ROLE_PREFIX, String.valueOf(result), 6, "0");
        sysRole.setCode(roleCode);

        sysRole.setCreateTime(new Date());
        int count = sysRoleMapper.insertSelective(sysRole);
        if (count != 1) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
        idControlService.updateCurrentVal(CommonConstant.ROLE_KEY, currentVal);
        //根菜单(permission中pid为0的)
        //List<SysPermission> permissionByTop = permissionService.getPermissionByTop();
        //List<Integer> permissions = vo.getPermissions();
        //permissionByTop.stream().forEach(p -> permissions.add(p.getId()));/
        if (null != vo.getPermissions() && !vo.getPermissions().isEmpty()) {
            RolePermissionOperationReqVO reqVO = new RolePermissionOperationReqVO();
            reqVO.setRoleId(sysRole.getId());
            reqVO.setPermissionIds(vo.getPermissions());
            rolePermissionService.addRolePermission(reqVO);
        }

        return sysRole;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateRole(RoleUpdateReqVO vo) {
        //查询其他id是否有同名的
        //只有名称不为空时才判断
        if (!StringUtils.isEmpty(vo.getName())) {
            List<SysRole> roleExitsList = sysRoleMapper.selectOthers(vo);
            if (!roleExitsList.isEmpty()) {
                throw new BusinessException(BaseResponseCode.ROLE_NAME_ALREADY_EXITS);
            }
        }
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(vo.getId());
        if (null == sysRole) {
            log.error("传入 的 id:{}不合法", vo.getId());
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        if (!sysRole.getStatus().equals(vo.getStatus()) && CommonConstant.STATUS.equals(vo.getStatus())) {
            //禁用角色时要先判断角色是否被使用
            List<Integer> roleIds = new ArrayList<>();
            roleIds.add(vo.getId());
            List<String> userIdsByRoleIds = userRoleService.getUserIdsByRoleIds(roleIds);
            if (!userIdsByRoleIds.isEmpty()) {
                throw new BusinessException(BaseResponseCode.ROLE_ALREADY_USED);
            }
        }
        //查看角色是否有人使用
        SysRole update = new SysRole();
        BeanUtils.copyProperties(vo, update);
        update.setUpdateTime(new Date());
        int count = sysRoleMapper.updateByPrimaryKeySelective(update);
        if (count != 1) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
       // rolePermissionService.removeByRoleId(sysRole.getId());
        QueryPermissionReqVo query = new QueryPermissionReqVo();
        //拿到当前登录人的可以修改角色时下的菜单
        List<SysPermission> list = permissionService.selectAll(query,null, "enableType");
        //查询修改前的角色拥有的菜单id
        List<Integer> permissionIdsByRoleId = rolePermissionService.getPermissionIdsByRoleId(vo.getId());
        Map<Integer, Integer>  permissionIdMap = permissionIdsByRoleId.stream()
                .collect(Collectors.toMap(Integer->Integer, Integer->Integer));

        //拿到前端送过来的需要更改的菜单，进行增加或删除
        if (null != vo.getPermissions() && !vo.getPermissions().isEmpty()) {
            Map<Integer, Integer>  voPermissionIdMap = vo.getPermissions().stream()
                    .collect(Collectors.toMap(Integer->Integer, Integer->Integer));
            //用户传的和本身所拥有的进行对比,对比出未选择的，如果未选择的数据存在permissionIdsByRoleId中，则进行删除
            List<Integer> notChooseList =new ArrayList<>();
            for (SysPermission sysPermission : list) {
                if(!voPermissionIdMap.containsKey(sysPermission.getId())){
                    notChooseList.add(sysPermission.getId());
                }
            }
            //如果两个list都存在，则无需做增删
            //如果原本存在，更新后不存在，则进行删除
            List<Integer> deletePermissionIds = new ArrayList<>();
            for (Integer permissionId : notChooseList) {
                if(!voPermissionIdMap.containsValue(permissionId)){
                    deletePermissionIds.add(permissionId);
                }
            }
            //如果原本不存在，更新后存在，则进行增加
            List<Integer> addPermissionIds = new ArrayList<>();
            for (Integer permission : vo.getPermissions()) {
                if(!permissionIdMap.containsValue(permission)){
                    addPermissionIds.add(permission);
                }
            }
            RolePermissionOperationReqVO reqVO = new RolePermissionOperationReqVO();
            reqVO.setRoleId(sysRole.getId());
            if (null != addPermissionIds && !addPermissionIds.isEmpty()) {
                //进行增加
                reqVO.setPermissionIds(addPermissionIds);
                rolePermissionService.addRolePermissions(reqVO);
            }
            if (null != deletePermissionIds && !deletePermissionIds.isEmpty()) {
                //进行删除
                reqVO.setPermissionIds(deletePermissionIds);
                rolePermissionService.deleteRolePermissions(reqVO);
            }


         /*   RolePermissionOperationReqVO reqVO = new RolePermissionOperationReqVO();
            reqVO.setRoleId(sysRole.getId());
            List<Integer> permissions = vo.getPermissions();
            //根菜单的那条数据不能删除(permission中 pid为0的不能删除)
            //List<SysPermission> permissionByTop = permissionService.getPermissionByTop();
            //permissionByTop.stream().forEach(p -> permissions.add(p.getId()));
            reqVO.setPermissionIds(vo.getPermissions());
            rolePermissionService.addRolePermission(reqVO);*/
        }
    }

    @Override
    public SysRole detailInfo(Integer id, String enableStatus) {
        SysRole sysRole = sysRoleMapper.selectByPrimaryKey(id);
        if (sysRole == null) {
            log.error("传入 的 id:{}不合法", id);
            throw new BusinessException(BaseResponseCode.DATA_ERROR);
        }
        //前端并没有用到permissionRespNodes,而是根据 /permission/tree/all 接口的全量数据, 再匹配这个接口的permissions集合进行选中匹配
        //所以各个集团的管理员,应该控制 /permission/tree/all这个接口的返回
        QueryPermissionReqVo query = new QueryPermissionReqVo();
        List<PermissionRespNode> permissionRespNodes = permissionService.selectAllByTree(query, enableStatus, null);
        List<Integer> permissionIds = rolePermissionService.getPermissionIdsByRoleId(sysRole.getId());
        Set<Integer> checkList = new HashSet<>(permissionIds);
        setheckced(permissionRespNodes, checkList);
        //sysRole.setPermissionRespNodes(permissionRespNodes);
        sysRole.setPermissions(permissionIds);

        return sysRole;
    }


    private void setheckced(List<PermissionRespNode> list, Set<Integer> checkList) {

        for (PermissionRespNode node : list) {

            if (checkList.contains(node.getId()) && (node.getChildren() == null || node.getChildren().isEmpty())) {
                node.setChecked(true);
            }
            setheckced((List<PermissionRespNode>) node.getChildren(), checkList);

        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deletedRole(Integer id) {
        //超级管理员不能删除
        SysRole sysRoleRecord = sysRoleMapper.selectByPrimaryKey(id);
        if (sysRoleRecord == null) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
        if (CommonConstant.SUPER_ROLE_CODE.equals(sysRoleRecord.getCode())) {
            throw new BusinessException(BaseResponseCode.SUPER_CANOT_DELETE);
        }
        //角色状态为启用状态不能删除
        if (CommonConstant.STATUS_FLAG .equals(sysRoleRecord.getStatus())) {
            throw new BusinessException(BaseResponseCode.ROLE_ENABLED_NOT_DELETED);
        }
        //系统内置角色不能操作
        if (sysRoleRecord.getCode().startsWith(CommonConstant.SYS_INNER_ROLE_PREFIX)) {
            throw new BusinessException(BaseResponseCode.INNER_ROLE_CANNOT_MODIFY);
        }
        SysRole sysRole = new SysRole();
        sysRole.setId(id);
        sysRole.setUpdateTime(new Date());
        sysRole.setDeleted(0);
        int count = sysRoleMapper.updateByPrimaryKeySelective(sysRole);
        if (count != 1) {
            throw new BusinessException(BaseResponseCode.OPERATION_ERRO);
        }
        List<String> userIds = sysUserRoleMapper.getInfoByUserIdByRoleId(id);
        rolePermissionService.removeByRoleId(id);
        userRoleService.removeByRoleId(id);

    }

    //清除角色所关联的

    @Override
    public PageVO<SysRole> pageInfo(RolePageReqVO vo) {
        PageHelper.startPage(vo.getPageNum(), vo.getPageSize());
        List<SysRole> sysRoles = sysRoleMapper.selectAll(vo);
        return PageUtilsOld.getPageVO(sysRoles);
    }

    @Override
    public List<SysRole> listInfo(RolePageReqVO vo) {
        vo.setStatus(1);
        List<SysRole> sysRoles = sysRoleMapper.selectAll(vo);
        return sysRoles;
    }

    @Override
    public List<SysRole> getRoleInfoByUserId(String userId) {

        List<Integer> roleIds = userRoleService.getRoleIdsByUserId(userId);
        if (roleIds.isEmpty()) {
            return null;
        }
        return sysRoleMapper.getRoleInfoByIds(roleIds);
    }

    @Override
    public List<SysRole> getRoleInfoByRoleIds(List<Integer> roleIds) {

        return sysRoleMapper.getRoleInfoByIds(roleIds);
    }

    @Override
    public List<String> getRoleNames(String userId) {

        List<SysRole> sysRoles = getRoleInfoByUserId(userId);
        if (null == sysRoles || sysRoles.isEmpty()) {
            return null;
        }
        List<String> list = new ArrayList<>();
        for (SysRole sysRole : sysRoles) {
            list.add(sysRole.getCode());
        }
        return list;
    }

    @Override
    public List<SysRole> selectAllRoles() {

        return sysRoleMapper.selectAll(new RolePageReqVO());
    }

    @Override
    public SysRole findRoleInfoByRoleCode(String roleCode) {
        SysRole sysRole = sysRoleMapper.findByCode(roleCode);
        return sysRole;
    }
}
