package com.gree.mall.manager.logic.admin;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.gree.mall.manager.bean.ExcelData;
import com.gree.mall.manager.bean.SVerification;
import com.gree.mall.manager.bean.admin.AdminModuleTree;
import com.gree.mall.manager.bean.admin.AdminUserCom;
import com.gree.mall.manager.bean.admin.AdminWebsitGrantBean;
import com.gree.mall.manager.bean.admin.ExternalMapBean;
import com.gree.mall.manager.bean.admin.reqDto.AdminUserAddReqBean;
import com.gree.mall.manager.bean.admin.reqDto.AdminUserPermissions;
import com.gree.mall.manager.commonmapper.AdminMapper;
import com.gree.mall.manager.enums.RedisPrefixEnum;
import com.gree.mall.manager.exception.RemoteServiceException;
import com.gree.mall.manager.logic.common.CommonLogic;
import com.gree.mall.manager.plus.entity.*;
import com.gree.mall.manager.plus.service.*;
import com.gree.mall.manager.utils.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class AdminUserLogic {

    private final RedisUtil redisUtil;

    private final DefaultKaptcha defaultKaptcha;

    private final CommonLogic commonLogic;

    private final AdminUserService adminUserService;

    private final AdminModuleService adminModuleService;

    private final AdminRoleService adminRoleService;

    private final AdminUserModuleRelaService adminUserModuleRelaService;

    private final AdminUserCompanyRelaService adminUserCompanyRelaService;

    private final AdminCompanyWechatService adminCompanyWechatService;

    private final AdminWebsitService adminWebsitService;

    private final AdminUserPermissionsRelaService adminUserPermissionsRelaService;

    private final AdminMapper adminMapper;

    private final AdminDeptService adminDeptService;

    private final AdminDeptWebsitService adminDeptWebsitService;

    @Value("${front.top.url}")
    private String frontTopUrl;

    /**
     * 验证码
     */
    public SVerification defaultKaptcha() throws IOException {
        // 生成文字验证码
        String text = defaultKaptcha.createText();

        // 生成图片验证码
        ByteArrayOutputStream outputStream = null;
        BufferedImage image = defaultKaptcha.createImage(text);
        outputStream = new ByteArrayOutputStream();
        ImageIO.write(image, "png", outputStream);
        byte b[] = outputStream.toByteArray();//从流中获取数据数组。
//        String baseStr = new BASE64Encoder().encode(b);
        String baseStr = Base64.getEncoder().encodeToString(b);
        //生成一个token
        String code = UUID.randomUUID().toString();
        redisUtil.set(RedisPrefixEnum.TOKEN_NEW_VERIFICATION + code, text, 2 * 60);
        SVerification verification = new SVerification();
        verification.setCode(code);
        verification.setPic(baseStr);
        return verification;
    }

    /**
     * 登录
     */
    public AdminUserCom login(String userName, String password, String code, String codeValue) throws RemoteServiceException {
        String value = (String) redisUtil.get(RedisPrefixEnum.TOKEN_NEW_VERIFICATION + code);
        if (StringUtils.isBlank(value) || !value.equals(codeValue)) {
            throw new RemoteServiceException("验证码错误");
        }
        AdminUser adminUser = adminUserService.lambdaQuery()
                .eq(AdminUser::getUserName, userName)
                .eq(AdminUser::getPassword, MD5Utils.md5(password))
                .one();
        if (adminUser == null) {
            throw new RemoteServiceException("帐号密码错误");
        }
        if (!adminUser.getStatus()) {
            throw new RemoteServiceException("帐号冻结中，请联系相关管理人员");
        }
        adminUser.setLastLoginTime(DateUtil.date());
        adminUser.updateById();

        AdminUserCom adminUserBean = new AdminUserCom();
        BeanUtils.copyProperties(adminUser, adminUserBean);
        //不返回密码
        adminUserBean.setPassword(null);
        adminUserBean.setToken(JwtUtils.createJWT(adminUser.getAdminUserId(), adminUser.getNickName(), adminUser.getUserName(), 20 * 60 * 60 * 1000));
        //查询用户在系统的关系
        adminUserBean = commonLogic.queryUserSysRela(adminUserBean);

        //存放到redis
        redisUtil.set(RedisPrefixEnum.TOKEN_NEW_MGR + adminUserBean.getToken(), adminUser, 20 * 60 * 60 * 1000);
        return adminUserBean;
    }

    /**
     * 修改密码
     */
    public void updatePassword(String userName, String password, String newPwd) throws RemoteServiceException {
        AdminUser adminUser = adminUserService.lambdaQuery().eq(AdminUser::getUserName, userName)
                .eq(AdminUser::getPassword, MD5Utils.md5(password)).one();
        if (adminUser == null) {
            throw new RemoteServiceException("帐号密码错误");
        }
        adminUser.setPassword(MD5Utils.md5(newPwd));
        adminUserService.updateById(adminUser);
    }

    /**
     * 修改帐号状态
     */
    public void updateStatus(String adminUserId, Boolean status) {
        adminUserService.lambdaUpdate().set(AdminUser::getStatus, status).eq(AdminUser::getAdminUserId, adminUserId).update();
    }

    /**
     * 重置密码
     */
    public void resetPassword(String adminUserId, String password, HttpServletRequest request) throws RemoteServiceException {
        //检查是否拥有重置的密码权限
        String nickName = CommonUtils.getNickName(request);
        if (!nickName.equals("admin")) {
            throw new RemoteServiceException("只有超级管理员才有重置密码的权限");
        }

        //开始重置
        AdminUser adminUser = adminUserService.getById(adminUserId);
        adminUser.setPassword(MD5Utils.md5(password));
        adminUser.updateById();
    }


    /**
     * 保存帐号
     */
    @Transactional
    public void save(AdminUserAddReqBean adminUser, HttpServletRequest request) throws RemoteServiceException {

        boolean isAdd = !StringUtils.isNotBlank(adminUser.getAdminUserId());

        AdminUserCom curLoginAmin = commonLogic.getAdminUser(request);

        if (StringUtils.isEmpty(adminUser.getUserName())
                || (isAdd && StringUtils.isEmpty(adminUser.getPassword()))) {
            throw new RemoteServiceException("参数错误");
        }
        Integer count = adminUserService.lambdaQuery()
                .ne(!isAdd, AdminUser::getAdminUserId, adminUser.getAdminUserId())
                .eq(AdminUser::getUserName, adminUser.getUserName())
                .count();
        if (count > 0) {
            throw new RemoteServiceException("帐号已被注册");
        }

        // 检查账号参数
        this.checkCreateAdminUserParams(adminUser, curLoginAmin, isAdd);

        // 数据权限
        if (!"admin".equals(adminUser.getUserName())) {
            this.dataPermissionsHandle(adminUser, adminUser.getPermissions(), adminUser.getDeptList());
        }

        if (isAdd || StringUtils.isNotBlank(adminUser.getPassword())) {
            adminUser.setPassword(MD5Utils.md5(adminUser.getPassword()));
        }

        adminUserService.saveOrUpdate(adminUser);
    }

    private void checkCreateAdminUserParams(AdminUserAddReqBean adminUser, AdminUserCom curLoginAmin, boolean isAdd) {
        if (!isAdd
                && adminUser.getAdminUserId().equals(curLoginAmin.getAdminUserId())
                && curLoginAmin.getUserName().equals("admin")) {
            throw new RemoteServiceException("不允许修改账号");
        }

        if (curLoginAmin.getType() == 0 && adminUser.getType() != 0) {
            if (StringUtils.isBlank(adminUser.getCompanyId()) || StringUtils.isBlank(adminUser.getCompanyName()) ) {
                throw new RemoteServiceException("管理员创建“非平台账号”账号，必须指定所属公司");
            }
        }

        // 检查账号类型
        if (curLoginAmin.getType() == 2 || curLoginAmin.getType() == 4) {
            // 如果创建人账号是商家, 所建账号为“商家类型”
            if (isAdd) {
                // 新增账号设值4=商家
                adminUser.setType(4);
            }
            if (CollectionUtil.isEmpty(adminUser.getPermissions())) {
                throw new RemoteServiceException("账号类型为“商家账号”, 请选择至少1个商家");
            }
            if (curLoginAmin.getType() == 4 && !adminUser.getType().equals(curLoginAmin.getType())) {
                throw new RemoteServiceException("操作者账号类型为“商家账号”, 只能操作选择“商家账号”");
            }
            adminUser.setCompanyId(curLoginAmin.getCompanyId());
            adminUser.setCompanyName(curLoginAmin.getCompanyName());
        } else if (curLoginAmin.getType() == 1 || curLoginAmin.getType() == 3) {
            // 如果创建人账号是商户, 所建账号为“商户类型”或“商家类型”
            if (adminUser.getType() == 0) {
                // 创建人账号不能选择平台
                throw new RemoteServiceException("操作者不能选择账号类型为“平台账号”");
            }
            if (CollectionUtil.isEmpty(adminUser.getDeptList()) && CollectionUtil.isEmpty(adminUser.getPermissions())) {
                throw new RemoteServiceException("账号类型为“商户账号”, 请选择至少1个部门或者1个商家");
            }
            adminUser.setCompanyId(curLoginAmin.getCompanyId());
            adminUser.setCompanyName(curLoginAmin.getCompanyName());
        }

        // 检查角色
        AdminRole addUserRole;
        if (StringUtils.isEmpty(adminUser.getRoleId()) ||
                (addUserRole = adminRoleService.getById(adminUser.getRoleId())) == null) {
            throw new RemoteServiceException("请为用户选择角色");
        }
        int requireSelectRoleType;
        if (adminUser.getType() == 2 || adminUser.getType() == 4) {
            requireSelectRoleType = 2;
        } else if (adminUser.getType() == 1 || adminUser.getType() == 3) {
            requireSelectRoleType = 1;
        } else {
            requireSelectRoleType = 0;
        }

        if (requireSelectRoleType != addUserRole.getType()) {
            throw new RemoteServiceException("账号类型与角色类型不匹配");
        }

        adminUser.setRoleName(addUserRole.getName());
        if (isAdd) {
            // 新增账号产生id
            adminUser.setAdminUserId(IdWorker.getIdStr());
        }
    }

    private void dataPermissionsHandle(AdminUserAddReqBean adminUser, List<AdminUserPermissions> permissions, List<AdminUserPermissions> deptList) {

        List<AdminDept> deptExistList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(deptList)) {

            final List<String> deptIdList = deptList.stream()
                    .map(AdminUserPermissions::getAdminUserPermissionsId)
                    .collect(Collectors.toList());

            deptExistList = adminDeptService.lambdaQuery()
                    .in(AdminDept::getAdminDeptId, deptIdList)
                    .list();

            if (deptExistList.size() < deptIdList.size()) {
                throw new RemoteServiceException("选择里有异常部门");
            }
        }

        final List<String> websitList = permissions.stream()
                .map(AdminUserPermissions::getAdminUserPermissionsId)
                .collect(Collectors.toList());

        List<AdminWebsit> websitExistList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(websitList)) {
            websitExistList = adminWebsitService.lambdaQuery()
                    .in(AdminWebsit::getWebsitId, websitList)
                    .list();

            if (websitExistList.size() < websitList.size()) {
                throw new RemoteServiceException("选择里有异常商家");
            }
        }

        // 清空权限关系
        adminUserPermissionsRelaService.lambdaUpdate()
                .eq(AdminUserPermissionsRela::getAdminUserId, adminUser.getAdminUserId())
                .remove();

        List<AdminUserPermissionsRela> relaList = new ArrayList<>();
        for (AdminDept adminDept : deptExistList) {
            AdminUserPermissionsRela rela = new AdminUserPermissionsRela();
            rela.setAdminUserId(adminUser.getAdminUserId())
                    .setAdminUserPermissionsId(adminDept.getAdminDeptId())
                    .setCompanyId(adminDept.getCompanyId())
                    .setIsDept(true);
            relaList.add(rela);
        }
        for (AdminWebsit adminWebsit : websitExistList) {
            AdminUserPermissionsRela rela = new AdminUserPermissionsRela();
            rela.setAdminUserId(adminUser.getAdminUserId())
                    .setAdminUserPermissionsId(adminWebsit.getWebsitId())
                    .setCompanyId(adminWebsit.getCompanyId())
                    .setIsDept(false);
            relaList.add(rela);
        }

        adminUserPermissionsRelaService.saveBatch(relaList);
    }


    /**
     * 运营后台用户列表
     *
     * @return
     */
    public IPage<AdminUser> list(String companyName,String roleId, Boolean status, String userName, Integer pageNum, Integer pageSize, HttpServletRequest request) {
        AdminUserCom adminUser = commonLogic.getAdminUser(request);

        Set<String> adminUserIdList = new HashSet<>();
        if (!adminUser.getUserName().equals("admin")) {
            // 非admin，筛选能看的账号
            this.queryCanSeeAdminUser(adminUserIdList, adminUser);
            adminUserIdList.add(adminUser.getAdminUserId());
        }

        IPage<AdminUser> page = adminUserService.lambdaQuery()
                .in(CollectionUtil.isNotEmpty(adminUserIdList), AdminUser::getAdminUserId, adminUserIdList)
                .ne(!adminUser.getUserName().equals("admin"), AdminUser::getUserName, "admin")
                .eq(StringUtils.isNotEmpty(roleId), AdminUser::getRoleId, roleId)
                .eq(status != null, AdminUser::getStatus, status)
                .and(v -> {
                    if (!adminUser.getUserName().equals("admin") && adminUser.getType().equals(0)) {
                        v.in(CollectionUtils.isNotEmpty(adminUser.getAdminCompanyIds()), AdminUser::getCompanyId, adminUser.getAdminCompanyIds())
                                .or()
                                .eq(AdminUser::getCompanyId, "");
                    } else {
                        v.in(CollectionUtils.isNotEmpty(adminUser.getAdminCompanyIds()), AdminUser::getCompanyId, adminUser.getAdminCompanyIds());
                    }
                })
                .like(StringUtils.isNotEmpty(userName), AdminUser::getUserName, userName)
                .page(new Page<>(pageNum, pageSize));
        return page;
    }

    private void queryCanSeeAdminUser(Set<String> adminUserIdList, AdminUserCom adminUser) {
        final List<AdminUserPermissionsRela> permissionsRelaList = adminUserPermissionsRelaService.lambdaQuery()
                .eq(AdminUserPermissionsRela::getAdminUserId, adminUser.getAdminUserId())
                .list();

        Set<String> deptIdList = new HashSet<>();

        // 商家id集合
        Set<String> websitIdList = permissionsRelaList.stream()
                .filter(v -> !v.getIsDept())
                .map(AdminUserPermissionsRela::getAdminUserPermissionsId)
                .collect(Collectors.toSet());

        final List<String> deptList = permissionsRelaList.stream()
                .filter(AdminUserPermissionsRela::getIsDept)
                .map(AdminUserPermissionsRela::getAdminUserPermissionsId)
                .distinct()
                .collect(Collectors.toList());

        if (CollectionUtil.isNotEmpty(deptList)) {
            // 找出部门下的商家
            for (String deptId : deptList) {
                final List<AdminDeptWebsit> adminDeptWebsits = adminDeptWebsitService.lambdaQuery()
                        .eq(AdminDeptWebsit::getAdminDeptId, deptId)
                        .list();
                final List<String> websitIds = adminDeptWebsits.stream()
                        .map(AdminDeptWebsit::getWebsitId)
                        .collect(Collectors.toList());
                websitIdList.addAll(websitIds);

                // 遍历部门递归找出子部门
                this.querySubDeptId(deptId, deptIdList);
                deptIdList.add(deptId);
            }
        }

        // 根据商家id集合查找有关联的账号
        List<AdminUserPermissionsRela> adminUserPermissionsRelaList = adminUserPermissionsRelaService.lambdaQuery()
                .select(AdminUserPermissionsRela::getAdminUserId)
                .in(AdminUserPermissionsRela::getAdminUserPermissionsId, websitIdList)
                .groupBy(AdminUserPermissionsRela::getAdminUserId)
                .list();

        if (CollectionUtil.isNotEmpty(deptIdList)) {
            final List<AdminUserPermissionsRela> relaDeptList = adminUserPermissionsRelaService.lambdaQuery()
                    .select(AdminUserPermissionsRela::getAdminUserId)
                    .in(AdminUserPermissionsRela::getAdminUserPermissionsId, deptIdList)
                    .groupBy(AdminUserPermissionsRela::getAdminUserId)
                    .list();
            adminUserPermissionsRelaList.addAll(relaDeptList);
        }

        List<String> queryAdminUserIdList = adminUserPermissionsRelaList.stream()
                .map(AdminUserPermissionsRela::getAdminUserId)
                .distinct()
//                .filter(v -> !v.equals(adminUser.getAdminUserId()))
                .collect(Collectors.toList());

        // 当前登录账号为商家需要排除商户、平台账号；当前登录账号为商户需要排除平台账号
        if (adminUser.getType() != 0) {
            List<AdminUser> adminUserList = adminUserService.lambdaQuery()
                    .select(AdminUser::getAdminUserId, AdminUser::getType)
                    .in(AdminUser::getAdminUserId, queryAdminUserIdList)
                    .list();
            final Map<Integer, List<AdminUser>> userTypeMap = adminUserList.stream().collect(Collectors.groupingBy(AdminUser::getType));

            // 当前登录账号为商户或主商家或商家账号类型
            if ((adminUser.getType() == 3 || adminUser.getType() == 2 || adminUser.getType() == 4)
                    && userTypeMap.containsKey(1)) {
                // 排除商户主账号
                this.clearNotCanSeeAdminUserId(userTypeMap, 1, queryAdminUserIdList);
            }

            // 当前登录账号为主商家或商家账号类型
            if ((adminUser.getType() == 2 || adminUser.getType() == 4)
                    && userTypeMap.containsKey(3)) {
                // 排除商户账号
                this.clearNotCanSeeAdminUserId(userTypeMap, 3, queryAdminUserIdList);
            }

            // 当前登录账号为商家账号类型
            if (adminUser.getType() == 4 && userTypeMap.containsKey(2)) {
                // 排除商家主账号
                this.clearNotCanSeeAdminUserId(userTypeMap, 2, queryAdminUserIdList);
            }

            if (userTypeMap.containsKey(0)) {
                // 排除平台账号
                this.clearNotCanSeeAdminUserId(userTypeMap, 0, queryAdminUserIdList);
            }
        }

        adminUserIdList.addAll(queryAdminUserIdList);
    }

    private void querySubDeptId(String deptId, Set<String> deptIdList) {
        final List<AdminDept> deptList = adminDeptService.lambdaQuery()
                .select(AdminDept::getAdminDeptId)
                .eq(AdminDept::getPId, deptId)
                .list();

        if (CollectionUtil.isEmpty(deptIdList)) {
            return;
        }

        for (AdminDept adminDept : deptList) {
            this.querySubDeptId(adminDept.getAdminDeptId(), deptIdList);
        }

        deptIdList.addAll(deptList.stream().map(AdminDept::getAdminDeptId).collect(Collectors.toSet()));
    }

    private void clearNotCanSeeAdminUserId(Map<Integer, List<AdminUser>> userTypeMap, int type, List<String> queryAdminUserIdList) {
        final List<String> adminUsers = userTypeMap.get(type).stream().map(AdminUser::getAdminUserId).collect(Collectors.toList());
        final List<String> userIdList = queryAdminUserIdList.stream()
                .filter(adminUsers::contains)
                .collect(Collectors.toList());

        queryAdminUserIdList.removeAll(userIdList);
    }

    /**
     * 商户列表
     */
    public IPage<AdminUser> list(String companyName,String userName, String nickName, String linkPhone, String email, Boolean status, Integer pageNum, Integer pageSize) {
        IPage<AdminUser> adminUserIPage = adminMapper.mchList(new Page(pageNum, pageSize), userName, nickName, linkPhone, email, status);
        return adminUserIPage;
    }


    /**
     * 导出商户列表
     */
    public ExcelData exportMch(List<AdminUser> list) {
        String[] titles = new String[]{"用户名", "负责人", "联系电话", "邮箱", "地址", "创建时间"};
        List<List<Object>> rows = new ArrayList<>();
        for (AdminUser adminUser : list) {
            List<Object> row = new ArrayList<>();
            row.add(adminUser.getUserName());
            row.add(adminUser.getNickName());
            row.add(adminUser.getLinkPhone());
            row.add(adminUser.getEmail());
            row.add(adminUser.getAddress());
            row.add(DateUtils.formatDate(adminUser.getCreateTime()));
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setRows(rows);
        excelData.setTitles(Arrays.asList(titles));
        excelData.setName("sheet1");
        return excelData;
    }

    /**
     * 运营后台用户详情
     *
     * @param adminUserId
     * @return
     */
    public AdminUserCom detail(String adminUserId) {
        AdminUser adminUser = adminUserService.getById(adminUserId);
        AdminUserCom adminUserBean = new AdminUserCom();
        BeanUtils.copyProperties(adminUser, adminUserBean);

        final List<AdminUserPermissionsRela> permissionsRelas = adminUserPermissionsRelaService.lambdaQuery()
                .eq(AdminUserPermissionsRela::getAdminUserId, adminUser.getAdminUserId())
                .list();

        final List<String> deptIds = permissionsRelas.stream()
                .filter(AdminUserPermissionsRela::getIsDept)
                .map(AdminUserPermissionsRela::getAdminUserPermissionsId)
                .collect(Collectors.toList());

        final List<String> websitIds = permissionsRelas.stream()
                .filter(v -> !v.getIsDept())
                .map(AdminUserPermissionsRela::getAdminUserPermissionsId)
                .collect(Collectors.toList());

        List<AdminUserPermissions> permissions = new ArrayList<>();
        List<AdminUserPermissions> deptList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(deptIds)) {
            for (String deptId : deptIds) {
                AdminUserPermissions bean = new AdminUserPermissions();
                bean.setAdminUserPermissionsId(deptId);
                deptList.add(bean);
            }
        }

        if (CollectionUtil.isNotEmpty(websitIds)) {
            for (String websitId : websitIds) {
                AdminUserPermissions bean = new AdminUserPermissions();
                bean.setAdminUserPermissionsId(websitId);
                permissions.add(bean);
            }
        }

        adminUserBean.setPermissionList(permissionsRelas);
        adminUserBean.setAdminDeptIds(deptIds);
        adminUserBean.setAdminWebsitIds(websitIds);
        adminUserBean.setDeptList(deptList);
        adminUserBean.setPermissions(permissions);

        return adminUserBean;
    }


    /**
     * 退出登录
     */
    public void logout(HttpServletRequest request) {
        String token = CommonUtils.getToken(request);
        redisUtil.del(RedisPrefixEnum.TOKEN_NEW_MGR + token);
    }


    /**
     * 根据登录帐号查询权限模块
     */
    public List<AdminModuleTree> queryAdminModule(String adminUserId) {
        //String adminUserId = CommonUtils.getUserId(request);
        AdminUser adminUser = adminUserService.getById(adminUserId);
        if (adminUser.getUserName().equals("admin")) {
            return this.queryAdminModuleTree(null, true, null, null);
        } else {
            return this.queryAdminModuleTree(adminUser.getRoleId(), false, null, null);
        }
    }

    /**
     * 给角色授权
     */
    @Transactional
    public void grantModules(AdminWebsitGrantBean adminWebsitGrantBean) {
        String roleId = adminWebsitGrantBean.getAdminRoleId();
        final Integer subSize = adminRoleService.lambdaQuery()
                .eq(AdminRole::getParentRoleId, roleId)
                .count();

        //1.生成权限
        List<AdminUserModuleRela> newList = new ArrayList<>();
        for (String adminModuleId : adminWebsitGrantBean.getAdminModuleIds()) {
            AdminUserModuleRela adminUserModuleRela = new AdminUserModuleRela();
            adminUserModuleRela.setAdminRoleId(roleId);
            adminUserModuleRela.setCreateTime(new Date());
            adminUserModuleRela.setStatus(true);
            adminUserModuleRela.setAdminModuleId(adminModuleId);
            adminUserModuleRela.setFlag(1);
            newList.add(adminUserModuleRela);
        }
        for (String adminModuleId : adminWebsitGrantBean.getAdminModuleIds2()) {
            AdminUserModuleRela adminUserModuleRela = new AdminUserModuleRela();
            adminUserModuleRela.setAdminRoleId(roleId);
            adminUserModuleRela.setCreateTime(new Date());
            adminUserModuleRela.setStatus(true);
            adminUserModuleRela.setAdminModuleId(adminModuleId);
            adminUserModuleRela.setFlag(0);
            newList.add(adminUserModuleRela);
        }

        // 当前角色授权存在子角色，需要对比新旧数据，新加权限不处理，找出去掉的权限清除子角色的相应权限
        if (subSize > 0) {
            final List<AdminUserModuleRela> oldRelaList = adminUserModuleRelaService.lambdaQuery().eq(AdminUserModuleRela::getAdminRoleId, roleId).list();
            // 对比出新数据没，旧数据有的roleId
            final List<String> newModuleIds = newList.stream().map(AdminUserModuleRela::getAdminModuleId).collect(Collectors.toList());
            List<String> removeSubModuleList = new ArrayList<>();
            for (AdminUserModuleRela oldRela : oldRelaList) {
                if (newModuleIds.contains(oldRela.getAdminModuleId())) {
                    continue;
                }
                removeSubModuleList.add(oldRela.getAdminModuleId());
            }
            if (CollectionUtil.isNotEmpty(removeSubModuleList)) {
                // 删除子角色关联菜单
                this.removeRelaSubModule(roleId, removeSubModuleList);
            }
        }

        //2.清空该角色的权限
        adminUserModuleRelaService.lambdaUpdate().eq(AdminUserModuleRela::getAdminRoleId, roleId).remove();

        adminUserModuleRelaService.saveBatch(newList);
    }

    // 递归执行删除子角色关联菜单
    private void removeRelaSubModule(String parentRoleId, List<String> removeSubModuleList) {
        final List<AdminRole> subRoleList = adminRoleService.lambdaQuery()
                .select(AdminRole::getAdminRoleId)
                .eq(AdminRole::getParentRoleId, parentRoleId)
                .list();

        if (CollectionUtil.isNotEmpty(subRoleList)) {
            final List<String> roleIds = subRoleList.stream()
                    .map(AdminRole::getAdminRoleId)
                    .collect(Collectors.toList());

            for (String moduleId : removeSubModuleList) {
                adminUserModuleRelaService.lambdaUpdate()
                        .eq(AdminUserModuleRela::getAdminModuleId, moduleId)
                        .in(AdminUserModuleRela::getAdminRoleId, roleIds)
                        .remove();
            }

            for (String roleId : roleIds) {
                this.removeRelaSubModule(roleId, removeSubModuleList);
            }
        }

    }

    /**
     * 根据角色id查询拥有的权限ids
     */
    public List<String> queryModuleIdChecked(String adminRoleId) {
        AdminRole adminRole = adminRoleService.getById(adminRoleId);
        Boolean admin = adminRole.getName().equals("超级管理员");
        if (admin) {
            List<AdminModule> list = adminModuleService.list();
            if (list.size() == 0) {
                return new ArrayList<>();
            }
            return list.stream().map(AdminModule::getModuleId).collect(Collectors.toList());
        }
        List<AdminUserModuleRela> list = adminUserModuleRelaService.lambdaQuery()
                .eq(AdminUserModuleRela::getAdminRoleId, adminRoleId).list();
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(AdminUserModuleRela::getAdminModuleId).collect(Collectors.toList());
    }

    /**
     * 根据角色查询所有功能模块权限
     */
    public List<AdminModuleTree> queryAllAdminModuleTree(String adminRoleId, HttpServletRequest request) {
        String userId = CommonUtils.getUserId(request);
        AdminUser adminUser = adminUserService.getById(userId);

        //更改的角色
        AdminRole adminRole = adminRoleService.getById(adminRoleId);
        //查询该角色有的权限d
        List<AdminUserModuleRela> hasModules = adminUserModuleRelaService.lambdaQuery().eq(AdminUserModuleRela::getAdminRoleId, adminRoleId).list();
        List<String> collect = new ArrayList<>();
        if (!CollectionUtils.isEmpty(hasModules)) {
            collect = hasModules.stream().map(AdminUserModuleRela::getAdminModuleId).collect(Collectors.toList());
        }
        List<AdminModuleTree> adminModuleTrees = this.queryAdminModuleTree(adminRoleId, adminRole.getName().equals("超级管理员"), collect, adminUser);
        return adminModuleTrees;
    }


    private List<AdminModuleTree> queryAdminModuleTree(String roleId, Boolean admin, List<String> hasModule, AdminUser adminUser) {

        List<AdminModule> adminModules = null;

        if (admin != null && !admin) {
            //非超管角色
            List<AdminUserModuleRela> list = adminUserModuleRelaService.lambdaQuery()
                    .eq(StringUtils.isNotEmpty(roleId), AdminUserModuleRela::getAdminRoleId, roleId)
                    .list();
            if (list.size() == 0) {
                return new ArrayList<>();
            }
            List<String> moduleIds = list.stream().map(AdminUserModuleRela::getAdminModuleId).collect(Collectors.toList());
            adminModules = adminModuleService.lambdaQuery().in(AdminModule::getModuleId, moduleIds)
                    .orderByAsc(AdminModule::getSortNum).list();
        } else {
            //超管角色
            List<AdminUserModuleRela> list = adminUserModuleRelaService.lambdaQuery().list();
            if (list.size() == 0) {
                return new ArrayList<>();
            }
            adminModules = adminModuleService.lambdaQuery().orderByAsc(AdminModule::getSortNum).list();
        }
        List<AdminModuleTree> trees = new ArrayList<>();
        for (AdminModule adminModule : adminModules) {
            AdminModuleTree adminModuleTree = new AdminModuleTree();
            BeanUtils.copyProperties(adminModule, adminModuleTree);
            if ((hasModule != null && hasModule.contains(adminModule.getModuleId())) || admin) {
                adminModuleTree.setShow(true);
            }
            trees.add(adminModuleTree);
        }
        List<AdminModuleTree> parents = trees.stream().filter(v -> v.getLevel() == 1).collect(Collectors.toList());
        for (AdminModuleTree adminModuleTree : parents) {
            adminModuleTree.setChildren(this.treeModule(trees, adminModuleTree.getModuleId(), hasModule, admin));
        }
        return parents;
    }

    private List<AdminModuleTree> treeModule(List<AdminModuleTree> list, String parentId, List<String> hasModule, Boolean admin) {
        //最父级资源树
        if (StringUtils.isEmpty(parentId)) {
            return new ArrayList<>();
        }
        List<AdminModuleTree> collect = list.stream().filter(e -> e.getParentId().equals(parentId)).collect(Collectors.toList());
        for (AdminModuleTree bean : collect) {
            if ((hasModule != null && hasModule.contains(bean.getModuleId())) || admin) {
                bean.setShow(true);
            }
            bean.setChildren(this.treeModule(list, bean.getModuleId(), hasModule, admin));
        }
        return collect;
    }


    public ExternalMapBean checkOrLoginAccount(String account, String password, Boolean isCheck, String timestamp, String sign) {
        String newSign = JiaSMUtil.jiasmDigest(account + password, timestamp);
        if (!newSign.equals(sign)) {
            throw new RemoteServiceException("请求不合法");
        }
        AdminUser adminUser = adminUserService.lambdaQuery()
                .eq(AdminUser::getUserName, account)
                .eq(AdminUser::getPassword, MD5Utils.md5(password))
                .one();
        if (Objects.isNull(adminUser)) {
            throw new RemoteServiceException(4040001, "请求不合法");
        }

        if (!adminUser.getStatus()) {
            throw new RemoteServiceException(4040001, "帐号冻结中，请联系相关管理人员");
        }
        if (!isCheck) {
            adminUser.setLastLoginTime(new Date());
            adminUser.updateById();

            AdminUserCom adminUserBean = new AdminUserCom();
            BeanUtils.copyProperties(adminUser, adminUserBean);
            //不返回密码
            adminUserBean.setPassword(null);
            adminUserBean.setToken(JwtUtils.createJWT(adminUser.getAdminUserId(), adminUser.getNickName(), adminUser.getUserName(), 20 * 60 * 60 * 1000));

            //存放到redis
            redisUtil.set(RedisPrefixEnum.TOKEN_NEW_MGR.toString() + adminUserBean.getToken(), adminUser, 20 * 60 * 60 * 1000);

            // 返回结果
            ExternalMapBean bean = new ExternalMapBean();
            bean.setToken(adminUserBean.getToken());
            bean.setUrl(frontTopUrl);
            bean.setUserid(adminUserBean.getAdminUserId());
            return bean;
        }
        return null;
    }
}
