package jnpf.authority.service.impl;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import jnpf.UpgradeApi;
import jnpf.attendance.service.AttendanceSuperAdminService;
import jnpf.authority.mapper.*;
import jnpf.authority.service.FtbPermissionFunctionMenuService;
import jnpf.authority.service.FtbPermissionMigrateService;
import jnpf.authority.service.FtbPermissionRoleAuthorizePersonService;
import jnpf.authority.service.FtbPermissionRoleService;
import jnpf.base.ActionResult;
import jnpf.base.ModuleApi;
import jnpf.base.SystemApi;
import jnpf.base.entity.ModuleBakUpEntity;
import jnpf.base.entity.ModuleButtonEntity;
import jnpf.base.entity.ModuleEntity;
import jnpf.base.entity.SystemEntity;
import jnpf.base.model.module.MenuListVO;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.model.UserMenuModel;
import jnpf.model.authority.dto.menu.FtbPermissionMenuDirectoryDTO;
import jnpf.model.authority.dto.menu.FtbPermissionMigrareRoleAddDTO;
import jnpf.model.authority.dto.menu.FtbPermissionRoleAddDTO;
import jnpf.model.authority.dto.person.FtbPermissionRolePersonAddDTO;
import jnpf.model.authority.dto.role.FtbPermissionPositionAuthorizationDTO;
import jnpf.model.authority.dto.role.FtbPermissionPositionMenuDTO;
import jnpf.model.authority.po.*;
import jnpf.model.authority.vo.menu.*;
import jnpf.model.authority.vo.role.FtbPermissionPositionMenuVO;
import jnpf.model.authority.vo.role.FtbPermissionRoleInfoVO;
import jnpf.model.config.PatrolUpgradeConfigUserVo;
import jnpf.model.personnels.po.FtbPersonnelsPermissions;
import jnpf.permission.V2PositionApi;
import jnpf.permission.dto.v2.position.QueryPositionUserListDTO;
import jnpf.permission.vo.v2.position.PositionListUserVO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.personnels.mapper.FtbPersonnelsPermissionsMapper;
import jnpf.util.AuthUtil;
import jnpf.util.JsonUtil;
import jnpf.util.treeutil.SumTree;
import jnpf.util.treeutil.newtreeutil.TreeDotUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class FtbPermissionMigrateServiceImpl implements FtbPermissionMigrateService {

    @Resource
    private UpgradeApi upgradeApi;

    @Resource
    private FtbPermissionFunctionMenuService ftbPermissionFunctionMenuService;

    @Resource
    private FtbPermissionMigrateMapper ftbPermissionMigrateMapper;

    @Resource
    private FtbPersonnelsPermissionsMapper ftbPersonnelsPermissionsMapper;

    @Resource
    private V2PositionApi v2PositionApi;

    @Resource
    private AttendanceSuperAdminService attendanceSuperAdminService;

    @Resource
    private FtbPermissionRoleService ftbPermissionRoleService;

    @Resource
    private FtbPermissionRoleAuthorizePersonService ftbPermissionRoleAuthorizePersonService;

    @Resource
    private SystemApi systemApi;

    @Resource
    private ModuleApi moduleApi;

    @Resource
    private FtbPermissionFunctionMenuMapper ftbPermissionFunctionMenuMapper;


    @Resource
    private FtbPermissionRoleMenuRelationMapper ftbPermissionRoleMenuRelationMapper;

    @Resource
    FtbPermissionRoleMenuMapper ftbPermissionRoleMenuMapper;

    @Resource
    FtbPermissionRolePersonUserRelationMapper ftbPermissionRolePersonUserRelationMapper;

    @Override
    public List<FtbPermissionPositionMenuVO> getPositionMenuByTenantAndModule(FtbPermissionPositionMenuDTO ftbPermissionPositionMenuDTO) {
        // 获取所有角色
        List<FtbPermissionRole> ftbPermissionRoles = ftbPermissionRoleService.list();
        List<String> roleNames = ftbPermissionRoles.stream().map(FtbPermissionRole::getRoleName).collect(Collectors.toList());
        // 查询所有岗位
        QueryPositionUserListDTO dto = new QueryPositionUserListDTO();
        ActionResult<List<PositionListUserVO>> listPositionTreeUser = v2PositionApi.listPositionTreeUser(dto);
        // 获取每个岗位下的人，没有人则不执行以下逻辑
        List<FtbPermissionPositionMenuVO> result = new ArrayList<>();
        List<PositionListUserVO> positionTreeUserData = listPositionTreeUser.getData();
        positionTreeUserData = positionTreeUserData.stream()
                .filter(data -> !roleNames.contains(ftbPermissionPositionMenuDTO.getModuleName() + "-" + data.getFullName()))
                .collect(Collectors.toList());
        for (PositionListUserVO datum : positionTreeUserData) {
            FtbPermissionPositionMenuVO ftbPermissionPositionMenuVO = new FtbPermissionPositionMenuVO();
            ftbPermissionPositionMenuVO.setPostName(datum.getFullName());
            ftbPermissionPositionMenuVO.setPostId(datum.getId());
            if (CollUtil.isNotEmpty(datum.getUserList())) {
                List<String> userIds = datum.getUserList().stream().map(UserBoundVO::getId).collect(Collectors.toList());
                ftbPermissionPositionMenuVO.setUserIds(userIds);
                // 获取岗位下用户的权限菜单
                if ("人事管理".equals(ftbPermissionPositionMenuDTO.getModuleName())) {
                    List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> ftbPermissionPositionMenuInnerVOS = personnelMenu(userIds, 0);
                    ftbPermissionPositionMenuVO.setFtbPermissionPositionMenuInnerVOList(ftbPermissionPositionMenuInnerVOS);
                } else if ("培训管理".equals(ftbPermissionPositionMenuDTO.getModuleName())) {
                    List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> ftbPermissionPositionMenuInnerVOS = personnelMenu(userIds, 1);
                    ftbPermissionPositionMenuVO.setFtbPermissionPositionMenuInnerVOList(ftbPermissionPositionMenuInnerVOS);
                } else if ("考勤管理".equals(ftbPermissionPositionMenuDTO.getModuleName())) {
                    List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> ftbPermissionPositionMenuInnerVOS = attendanceSuperAdminService.queryPermissionListByUserIds(userIds);
                    ftbPermissionPositionMenuVO.setFtbPermissionPositionMenuInnerVOList(ftbPermissionPositionMenuInnerVOS);
                }
            }
            result.add(ftbPermissionPositionMenuVO);
        }
        result = result.stream().filter(a -> CollUtil.isNotEmpty(a.getFtbPermissionPositionMenuInnerVOList())).collect(Collectors.toList());
        // 获取2.0权限菜单
        FtbPermissionMenuDirectoryDTO ftbPermissionMenuDTO = new FtbPermissionMenuDirectoryDTO();
        ftbPermissionMenuDTO.setTenantId(ftbPermissionPositionMenuDTO.getTenantId());
        ftbPermissionMenuDTO.setId(ftbPermissionPositionMenuDTO.getMenuWebId());
        List<FtbPermissionMenuConfigTreeVO> menuConfigurationsWeb = ftbPermissionFunctionMenuService.getAListOfFunctionMenuConfigurations(ftbPermissionMenuDTO);
        ftbPermissionMenuDTO.setId(ftbPermissionPositionMenuDTO.getMenuAppId());
        List<FtbPermissionMenuConfigTreeVO> menuConfigurationsApp = ftbPermissionFunctionMenuService.getAListOfFunctionMenuConfigurations(ftbPermissionMenuDTO);
        // 判断结果数组不为空
        if (CollUtil.isEmpty(result)) {
            return result;
        }
        result.get(0).setFtbPermissionMenuConfigTreeVOListWeb(menuConfigurationsWeb);
        result.get(0).setFtbPermissionMenuConfigTreeVOListApp(menuConfigurationsApp);
        return result;
    }

    @Override
    @Transactional
    public void syncPositionAuthorization(FtbPermissionPositionAuthorizationDTO ftbPermissionPositionAuthorizationDTO) {
        List<FtbPermissionRole> roleList = new ArrayList<>();
        List<FtbPermissionRoleMenu> roleMenuList = new ArrayList<>();
        List<FtbPermissionRoleMenuRelation> roleMenuRelationList = new ArrayList<>();
        List<FtbPermissionRoleAuthorizePost> roleAuthorizePostList = new ArrayList<>();
        List<FtbPermissionRolePersonUserRelation> rolePersonUserRelationList = new ArrayList<>();
        // 人事管理和培训同步用户数据权限
        List<String> userIds = ftbPermissionPositionAuthorizationDTO.getPositionList()
                .stream()
                .filter(a -> CollUtil.isNotEmpty(a.getUserIds()))
                .flatMap(a -> a.getUserIds().stream())
                .collect(Collectors.toList());
        LambdaQueryWrapper<FtbPersonnelsPermissions> ftbPersonnelsPermissionsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        ftbPersonnelsPermissionsLambdaQueryWrapper.in(FtbPersonnelsPermissions::getUserId, userIds);
        ftbPersonnelsPermissionsLambdaQueryWrapper.eq(FtbPersonnelsPermissions::getEnableMark, 0);
        List<FtbPersonnelsPermissions> ftbPersonnelsPermissions = new ArrayList<>();
        if ("人事管理".equals(ftbPermissionPositionAuthorizationDTO.getModuleName())) {
            ftbPersonnelsPermissionsLambdaQueryWrapper.eq(FtbPersonnelsPermissions::getPermissionType, 0);
            ftbPersonnelsPermissions = ftbPersonnelsPermissionsMapper.selectList(ftbPersonnelsPermissionsLambdaQueryWrapper);
        } else if ("培训管理".equals(ftbPermissionPositionAuthorizationDTO.getModuleName())) {
            ftbPersonnelsPermissionsLambdaQueryWrapper.eq(FtbPersonnelsPermissions::getPermissionType, 1);
            ftbPersonnelsPermissions = ftbPersonnelsPermissionsMapper.selectList(ftbPersonnelsPermissionsLambdaQueryWrapper);
        }
        final List<FtbPersonnelsPermissions> finalFtbPersonnelsPermissions = ftbPersonnelsPermissions;
        // 数据组装
        ftbPermissionPositionAuthorizationDTO.getPositionList().forEach(positionInnerDTO -> {
            if (CollUtil.isNotEmpty(positionInnerDTO.getUserIds()) && CollUtil.isNotEmpty(positionInnerDTO.getPermissionRoleInners())) {
                FtbPermissionRole ftbPermissionRole = new FtbPermissionRole();
                ftbPermissionRole.setRoleName(ftbPermissionPositionAuthorizationDTO.getModuleName() + "-" + positionInnerDTO.getPostName());
                ftbPermissionRole.setId(IdWorker.getIdStr());
                // 权限管理角色菜单
                positionInnerDTO.getPermissionRoleInners().stream()
                        .filter(a -> CollUtil.isNotEmpty(a.getMemberIds()))
                        .forEach(a -> {
                            FtbPermissionRoleMenu ftbPermissionRoleMenu = a.convert(a);
                            ftbPermissionRoleMenu.setRoleEnabled(1);
                            ftbPermissionRoleMenu.setScopePermission(1);
                            ftbPermissionRoleMenu.setRoleId(ftbPermissionRole.getId());
                            ftbPermissionRoleMenu.setId(IdWorker.getIdStr());
                            List<FtbPermissionRoleMenuRelation> ftbPermissionRoleMenuRelations = a.getMemberIds().stream()
                                    .map(b -> {
                                        FtbPermissionRoleMenuRelation formRelation = new FtbPermissionRoleMenuRelation();
                                        formRelation.setId(IdWorker.getIdStr());
                                        formRelation.setRoleId(ftbPermissionRole.getId());
                                        formRelation.setRoleMenuConfigId(b);
                                        formRelation.setRoleMenuId(ftbPermissionRoleMenu.getId());
                                        return formRelation;
                                    }).collect(Collectors.toList());
                            // 角色菜单表
                            roleMenuList.add(ftbPermissionRoleMenu);
                            // 角色菜单关联表
                            roleMenuRelationList.addAll(ftbPermissionRoleMenuRelations);
                        });
                // 岗位授权表
                FtbPermissionRoleAuthorizePost ftbPermissionRoleAuthorizePost = new FtbPermissionRoleAuthorizePost();
                ftbPermissionRoleAuthorizePost.setRoleId(ftbPermissionRole.getId());
                ftbPermissionRoleAuthorizePost.setPostId(positionInnerDTO.getPostId());
                ftbPermissionRoleAuthorizePost.setEnableMark(0L);
                ftbPermissionRoleAuthorizePost.setId(IdWorker.getIdStr());
                roleAuthorizePostList.add(ftbPermissionRoleAuthorizePost);
                // 人员个人权限表
                if (CollUtil.isNotEmpty(finalFtbPersonnelsPermissions)) {
                    Map<String, FtbPersonnelsPermissions> ftbPersonnelsPermissionsMap = finalFtbPersonnelsPermissions.stream()
                            .collect(Collectors.toMap(FtbPersonnelsPermissions::getUserId, a -> a));
                    positionInnerDTO.getUserIds().forEach(a -> {
                        FtbPersonnelsPermissions ftbPersonnelPermissions = ftbPersonnelsPermissionsMap.get(a);
                        if (ftbPersonnelPermissions != null) {
                            FtbPermissionRolePersonUserRelation followerUserRelation = new FtbPermissionRolePersonUserRelation();
                            followerUserRelation.setId(IdWorker.getIdStr());
                            followerUserRelation.setUserId(a);
                            followerUserRelation.setRoleEnabled(1);
                            followerUserRelation.setFunctionAppId(ftbPermissionPositionAuthorizationDTO.getMenuAppId());
                            followerUserRelation.setFunctionWebId(ftbPermissionPositionAuthorizationDTO.getMenuWebId());
                            // 根据汉字转换映射
                            Integer convertScopePermission = convertScopePermission(ftbPersonnelPermissions.getScopePermission());
                            followerUserRelation.setScopePermission(convertScopePermission);
                            if (convertScopePermission == 4) {
                                followerUserRelation.setSpecifyOrgIds(ftbPersonnelPermissions.getSpecifyOrgIds());
                            }
                            rolePersonUserRelationList.add(followerUserRelation);
                        }
                    });
                }
                // 角色表
                roleList.add(ftbPermissionRole);
            }
        });
        Db.saveBatch(roleList);
        Db.saveBatch(roleMenuList);
        Db.saveBatch(roleMenuRelationList);
        Db.saveBatch(roleAuthorizePostList);
        Db.saveBatch(rolePersonUserRelationList);
    }

    @Override
    public List<Map<String, Object>> getRoleList(String tenantId) {
        try {
            TenantDataSourceUtil.switchTenant(tenantId);
        } catch (LoginException e) {
            throw new RuntimeException(e);
        }
        return ftbPermissionMigrateMapper.getRoleList();
    }

    @Override
    @Transactional
    public void addRole(FtbPermissionMigrareRoleAddDTO ftbPermissionRole) {
        String tenantId = ftbPermissionRole.getTenantId();
        try {
            TenantDataSourceUtil.switchTenant(tenantId);
        } catch (LoginException e) {
            throw new RuntimeException(e);
        }
        // 迁移同一个id
        String roleId = ftbPermissionRole.getRoleId();
        LambdaQueryWrapper<FtbPermissionRole> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPermissionRole::getId, roleId);
        FtbPermissionRole one = ftbPermissionRoleService.getOne(queryWrapper);
        if (ObjectUtil.isEmpty(one)) {
            ftbPermissionRole.setId(roleId);
            // 角色名称不能重复
            LambdaQueryWrapper<FtbPermissionRole> queryWrapper2 = Wrappers.lambdaQuery();
            queryWrapper2.eq(FtbPermissionRole::getRoleName, ftbPermissionRole.getRoleName());
            queryWrapper2.eq(FtbPermissionRole::getEnableMark, 0);
            if (ftbPermissionRoleService.count(queryWrapper) > 0) {
                throw new RuntimeException("角色名称不可重复!");
            }
            FtbPermissionRole permissionRole = new FtbPermissionRole();
            permissionRole.setId(ftbPermissionRole.getId());
            permissionRole.setRoleName(ftbPermissionRole.getRoleName());
            permissionRole.setRoleDescription(ftbPermissionRole.getRoleDescription());
            ftbPermissionRoleService.save(permissionRole);
            List<FtbPermissionRoleAddDTO.PermissionRoleInnerDTO> permissionRoleInners = ftbPermissionRole.getPermissionRoleInners();
            extracted(permissionRoleInners, roleId);
        }else {
            // 修改逻辑
            LambdaQueryWrapper<FtbPermissionRoleMenu> roleMenuLambdaQueryWrapper = new LambdaQueryWrapper<FtbPermissionRoleMenu>()
                    .eq(FtbPermissionRoleMenu::getRoleId, roleId);
            // 删除菜单关联信息
            ftbPermissionRoleMenuMapper.delete(roleMenuLambdaQueryWrapper);
            LambdaQueryWrapper<FtbPermissionRoleMenuRelation> deleteRoleWrapper = new LambdaQueryWrapper<FtbPermissionRoleMenuRelation>()
                    .eq(FtbPermissionRoleMenuRelation::getRoleId, roleId);
            ftbPermissionRoleMenuRelationMapper.delete(deleteRoleWrapper);
            List<FtbPermissionRoleAddDTO.PermissionRoleInnerDTO> permissionRoleInners = ftbPermissionRole.getPermissionRoleInners();
            if (CollUtil.isNotEmpty(permissionRoleInners)) {
                extracted(permissionRoleInners, roleId);
            }
        }
        // 多个已勾选模块id
        List<String> functionWebIds = ftbPermissionRole.getPermissionRoleInners().stream().map(FtbPermissionRoleAddDTO.PermissionRoleInnerDTO::getFunctionPageWebId).collect(Collectors.toList());
        // 根据勾选id查询模块名称 巡店同步权限
        List<ModuleEntity> moduleApiById = moduleApi.getById(functionWebIds, tenantId);
        ModuleEntity entity = moduleApiById.stream().filter(v -> "巡店管理".equals(v.getFullName())).findFirst().orElse(null);
        if (ObjectUtils.isNotEmpty(entity)) {
            String id = entity.getId();
            ActionResult<List<PatrolUpgradeConfigUserVo>> configUser = upgradeApi.getConfigUser(tenantId);
            if (configUser.getCode() == 200 && CollUtil.isNotEmpty(configUser.getData())){
                // 分别角色授权
                // 1
                List<String> isStoreHeadUserId = filterPersonnelInformation(configUser,v -> 1 == v.getIsStoreHeadUserId());
                addedPersonalAuthorization(isStoreHeadUserId, id,1);
                // 0
                List<String> dbUser = filterPersonnelInformation(configUser,v ->  1 == v.getIsDdUser());
                addedPersonalAuthorization(dbUser, id,0);
                // 0
                List<String> isCheckUser = filterPersonnelInformation(configUser,v -> 1 == v.getIsCheckUser());
                addedPersonalAuthorization(isCheckUser, id,0);
            }
        }
        // 根据id查询角色绑定人员信息
        List<String> userIds = ftbPermissionMigrateMapper.getUserListWithRoleId(roleId);
        // 进行授权
        FtbPermissionRolePersonAddDTO personAddDTO = new FtbPermissionRolePersonAddDTO();
        personAddDTO.setRoleId(roleId);
        personAddDTO.setUserIds(userIds);
        LambdaQueryWrapper<FtbPermissionRoleAuthorizePerson> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPermissionRoleAuthorizePerson::getRoleId, roleId);
        ftbPermissionRoleAuthorizePersonService.remove(wrapper);
        //  新增数据
        ftbPermissionRoleAuthorizePersonService.add(personAddDTO);
        // 下线数据
        userIds.forEach(AuthUtil::kickoutByUserId) ;
    }

    private void extracted(List<FtbPermissionRoleAddDTO.PermissionRoleInnerDTO> permissionRoleInners, String roleId) {
        // 权限管理角色菜单
        permissionRoleInners.stream()
                .filter(a -> CollUtil.isNotEmpty(a.getMemberIds()))
                .forEach(a -> {
                    FtbPermissionRoleMenu ftbPermissionRoleMenu = a.convert(a);
                    // 默认设置为所在组织及下级组织
                    ftbPermissionRoleMenu.setScopePermission(1);
                    ftbPermissionRoleMenu.setRoleId(roleId);
                    ftbPermissionRoleMenuMapper.insert(ftbPermissionRoleMenu);
                    List<FtbPermissionRoleMenuRelation> ftbPermissionRoleMenuRelations = a.getMemberIds().stream()
                            .map(b -> {
                                FtbPermissionRoleMenuRelation formRelation = new FtbPermissionRoleMenuRelation();
                                formRelation.setRoleId(roleId);
                                formRelation.setRoleMenuConfigId(b);
                                formRelation.setRoleMenuId(ftbPermissionRoleMenu.getId());
                                return formRelation;
                            }).collect(Collectors.toList());
                    Db.saveBatch(ftbPermissionRoleMenuRelations);
                });
    }

    /**
     * 给个人授权
     * @param userIds
     * @param moduleId
     */
    public void addedPersonalAuthorization(List<String> userIds,String moduleId,Integer scopePermission){
        if (CollUtil.isEmpty(userIds)){
            return;
        }
        // 先清空数据
        LambdaQueryWrapper<FtbPermissionRolePersonUserRelation> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(FtbPermissionRolePersonUserRelation::getUserId, userIds);
        queryWrapper.eq(FtbPermissionRolePersonUserRelation::getFunctionWebId,moduleId);
        ftbPermissionRolePersonUserRelationMapper.delete(queryWrapper);
        List<FtbPermissionRolePersonUserRelation> userRelations = userIds.stream().map(v -> {
            FtbPermissionRolePersonUserRelation userRelation = new FtbPermissionRolePersonUserRelation();
            userRelation.setUserId(v);
            userRelation.setFunctionWebId(moduleId);
            userRelation.setScopePermission(scopePermission);
            userRelation.setRoleEnabled(1);
            return userRelation;
        }).collect(Collectors.toList());
        Db.saveBatch(userRelations);
        userIds.forEach(AuthUtil::kickoutByUserId);
    }
    @NotNull
    private  List<String> filterPersonnelInformation(ActionResult<List<PatrolUpgradeConfigUserVo>> configUser,
                                                     Predicate<PatrolUpgradeConfigUserVo> predicate) {
        return configUser.getData().stream().filter(predicate).map(PatrolUpgradeConfigUserVo::getUserId).collect(Collectors.toList());
    }

    @Override
    public FtbPermissionModuleInfoVO queryRolePermission(String roleId, String tenantId) {
        try {
            TenantDataSourceUtil.switchTenant(tenantId);
        } catch (LoginException e) {
            throw new RuntimeException(e);
        }
        return permissionMenuBuild(roleId, tenantId);
    }

    @Override
    public List<FtbPermissionMenuDirectoryVO> getAListOfMenuDirectory(Integer type, String tenantId) {
        List<FtbPermissionMenuDirectoryVO> aListOfMenuDirectory = getAListOfMenuDirectory(tenantId);
        List<String> menuNames = List.of("人事管理", "培训管理", "考勤管理");
        return aListOfMenuDirectory.stream().filter(a -> {
            if (type == 0) {
                return menuNames.contains(a.getFullName());
            } else {
                return !menuNames.contains(a.getFullName());
            }
        }).collect(Collectors.toList());
    }

    /**
     * 角色权限菜单构建
     * @param roleId
     * @param tenantId
     * @return
     */
    public FtbPermissionModuleInfoVO permissionMenuBuild(String roleId, String tenantId){
        SystemEntity systemVO = systemApi.getSystemVONoToken(tenantId);
        String systemId = systemVO.getId();
        FtbPermissionRoleInfoVO vo = new FtbPermissionRoleInfoVO();
        if (roleId != null ){
            vo = ftbPermissionFunctionMenuMapper.getRoleWithMenu(roleId);
        }
        FtbPermissionModuleInfoVO infoVO = new FtbPermissionModuleInfoVO();
        List<FtbPermissionModuleVO> moduleVOSBak = buildData1(systemId, tenantId, vo, roleId);
        infoVO.setPermissionsOne(moduleVOSBak);
        List<FtbPermissionModuleVO> moduleVOS = buildData2(systemId, tenantId, vo, roleId);
        infoVO.setPermissionsTwo(moduleVOS);
        return infoVO;
    }
    public List<FtbPermissionModuleVO> buildData1(String systemId, String tenantId, FtbPermissionRoleInfoVO vo, String
            roleId){
        List<ModuleEntity> data = moduleApi.getModuleWithSystemId(systemId,  tenantId);
        if (CollUtil.isEmpty(data)) {
            throw new RuntimeException("未找到1.0菜单模块备份表,请先执行1.0备份语句进行权限同步!");
        }
        List<FtbPermissionMenuDirectoryVO> permissionMenuDirectoryVOS = getMenuDirectoryVOS(roleId, data, vo);
        List<String> relations = ftbPermissionMigrateMapper.characterCheckedMenusAndButtons(roleId);
        return permissionMenuDirectoryVOS.stream().map(v -> {
            FtbPermissionModuleVO moduleVO = new FtbPermissionModuleVO();
            moduleVO.setModuleName(v.getFullName());
            List<FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO> directoryInfoVOS = v.getChildren();
            List<FtbPermissionModuleVO.FtbPermissionMenuDirectory> directoryList = new ArrayList<>();
            // 代码复用
            shareCode1("Web", directoryInfoVOS, tenantId, roleId, relations, directoryList);
            shareCode1("App", directoryInfoVOS, tenantId, roleId, relations, directoryList);
            moduleVO.setDirectoryInfoVO(directoryList);
            return moduleVO;
        }).collect(Collectors.toList());
    }
    public List<FtbPermissionModuleVO> buildData2(String systemId, String tenantId, FtbPermissionRoleInfoVO vo, String
            roleId){
        List<ModuleEntity> dataBakUp = moduleApi.getListWithoutSystemId(systemId, null, null, tenantId);
        List<FtbPermissionMenuDirectoryVO> permissionMenuDirectoryVOS = getMenuDirectoryVOS(roleId, dataBakUp, vo);
        // 查询当前角色的菜单配置
        LambdaQueryWrapper<FtbPermissionRoleMenuRelation> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPermissionRoleMenuRelation::getRoleId, roleId);
        List<FtbPermissionRoleMenuRelation> relations2 = ftbPermissionRoleMenuRelationMapper.selectList(wrapper);
        return permissionMenuDirectoryVOS.stream().map(v -> {
            FtbPermissionModuleVO moduleVO = new FtbPermissionModuleVO();
            moduleVO.setModuleName(v.getFullName());
            List<FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO> directoryInfoVOS = v.getChildren();
            List<FtbPermissionModuleVO.FtbPermissionMenuDirectory> directoryList = new ArrayList<>();
            // 代码复用
            shareCode2("Web", directoryInfoVOS, tenantId, roleId, relations2, directoryList);
            shareCode2("App", directoryInfoVOS, tenantId, roleId, relations2, directoryList);
            moduleVO.setDirectoryInfoVO(directoryList);
            return moduleVO;
        }).collect(Collectors.toList());
    }

    /**
     * 构建统一数据2.0
     * @return
     */
    public  void shareCode2(String category,
                            List<FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO> directoryInfoVOS,
                            String tenantId,
                            String roleId,
                            List<FtbPermissionRoleMenuRelation> relations2,
                            List<FtbPermissionModuleVO.FtbPermissionMenuDirectory> directoryList){
        FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO infoVO = directoryInfoVOS.stream().filter(c->category.equals(c.getCategory())).findFirst().orElse(null);
        if (infoVO == null) return;
        String mod = infoVO.getId();
        FtbPermissionModuleVO.FtbPermissionMenuDirectory directory = new FtbPermissionModuleVO.FtbPermissionMenuDirectory();
        directory.setId(infoVO.getId());
        directory.setCategory(infoVO.getCategory());
        // 查询所有子集
        List<ModuleEntity> newData = new ArrayList<>();
        getTreeMenuWithPreantId2(mod, tenantId, newData);
        List<UserMenuModel> list = JsonUtil.getJsonToList(newData, UserMenuModel.class);
        List<SumTree<UserMenuModel>> menuList = TreeDotUtils.convertListToTreeDot(list);
        List<MenuListVO> toList = JsonUtil.getJsonToList(menuList, MenuListVO.class);
        // 根据所有的子集查询是否配置的菜单且需要递归获取配置进行复原
        // 构建2.0菜单详情
        List<FtbPermissionMenuConfigTreeVO> configTreeVOS = menuDetails2(roleId, toList, relations2);
        directory.setPermissionsMenu(configTreeVOS);
        directoryList.add(directory);
    }

    /**
     * 构建统一数据1.0
     * @return
     */
    public  void shareCode1(String category,
                            List<FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO> directoryInfoVOS,
                            String tenantId,
                            String roleId,
                            List<String> relations,
                            List<FtbPermissionModuleVO.FtbPermissionMenuDirectory> directoryList){
        FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO infoVO = directoryInfoVOS.stream().filter(c->category.equals(c.getCategory())).findFirst().orElse(null);
        if (infoVO == null) return;
        String mod = infoVO.getId();
        FtbPermissionModuleVO.FtbPermissionMenuDirectory directory = new FtbPermissionModuleVO.FtbPermissionMenuDirectory();
        directory.setId(infoVO.getId());
        directory.setCategory(infoVO.getCategory());
        // 查询所有子集
        List<ModuleEntity> newData = new ArrayList<>();
        getTreeMenuWithPreantId(mod, tenantId, newData);
        List<UserMenuModel> list = JsonUtil.getJsonToList(newData, UserMenuModel.class);
        List<SumTree<UserMenuModel>> menuList = TreeDotUtils.convertListToTreeDot(list);
        List<MenuListVO> toList = JsonUtil.getJsonToList(menuList, MenuListVO.class);
        // 根据所有的子集查询是否配置的菜单且需要递归获取配置进行复原
        // 构建1.0菜单详情
        List<FtbPermissionMigrateRoleTreeVO> configTreeVOS = menuDetails1(roleId, toList, relations);
        directory.setPermissionsMenu(configTreeVOS);
        directoryList.add(directory);
    }

    /**
     * 构建菜单
     * @param roleId
     * @param data
     * @param vo
     * @return
     */
    @NotNull
    private static List<FtbPermissionMenuDirectoryVO> getMenuDirectoryVOS(String roleId, List<ModuleEntity> data, FtbPermissionRoleInfoVO vo) {
        // 获取顶级目录菜单
        List<ModuleEntity> entities = data.stream().filter(item -> item.getType() != null && item.getEnabledMark() != null && 1 == item.getEnabledMark() && "-1".equals(item.getParentId())).collect(Collectors.toList());
        // 父级菜单
        List<FtbPermissionMenuDirectoryVO> directoryVOS = entities.stream().map(FtbPermissionMenuDirectoryVO::convert).distinct().collect(Collectors.toList());
        for (FtbPermissionMenuDirectoryVO directoryVO : directoryVOS) {
            List<FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO> infoVOS = entities.stream().filter(v -> v.getFullName().equals(directoryVO.getFullName())).map(v -> {
                FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO infoVO = new FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO();
                String vCategory = v.getCategory();
                String vId = v.getId();
                infoVO.setId(vId);
                infoVO.setCategory(vCategory);
                return infoVO;
            }).collect(Collectors.toList());
            if (StringUtils.isNotEmpty(roleId) && vo != null) {
                List<String> functionIds  = new ArrayList<>();
                if ( vo.getFunctionWebId() != null ){
                    String[] split = vo.getFunctionWebId().split(",");
                    functionIds .addAll(List.of(split));
                }
                if ( vo.getFunctionAppId() != null ){
                    functionIds.addAll(List.of(vo.getFunctionAppId().split(",")));
                }
                // 拼接并过滤非空字段
                functionIds.removeIf(StrUtil::isBlank);
                List<String> fullNames = entities.stream()
                        .filter(item -> functionIds.contains(item.getId()))
                        .map(ModuleEntity::getFullName).distinct().collect(Collectors.toList());
                if (fullNames.contains(directoryVO.getFullName())) {
                    directoryVO.setIsUse(true);
                }
            }
            // 全部保留
            directoryVO.setChildren(infoVOS);
        }
        return directoryVOS.stream()
                .filter(item -> !FtbPermissionFunctionMenuServiceImpl.EXCLUDED_DIRECTORIES.contains(item.getFullName()))
                .collect(Collectors.toList());
    }

    /**
     * 构建1.0菜单详情
     *
     * @param roleId
     * @param toList
     * @param relations
     * @return
     */
    private List<FtbPermissionMigrateRoleTreeVO> menuDetails1(String roleId, List<MenuListVO> toList, List<String> relations) {
        List<FtbPermissionMigrateRoleTree> configTrees = new ArrayList<>();
        buildMenuDetails1(toList, configTrees);
        if (roleId != null && CollUtil.isNotEmpty(relations)) {
            configTrees.forEach(item -> {
                boolean anyMatch = relations.stream().anyMatch(relation -> relation.equals(item.getId()));
                if (anyMatch) {
                    item.setIsChecked(true);
                }
            });
        }
        List<SumTree<FtbPermissionMigrateRoleTree>> trees = TreeDotUtils.convertListToTreeDot(configTrees);
        return JsonUtil.getJsonToList(trees, FtbPermissionMigrateRoleTreeVO.class);
    }


    /**
     * 构建2.0菜单详情
     *
     * @param roleId
     * @param toList
     * @return
     */
    private List<FtbPermissionMenuConfigTreeVO> menuDetails2(String roleId, List<MenuListVO> toList, List<FtbPermissionRoleMenuRelation> relations) {
        List<FtbPermissionMenuConfigTree> configTrees = new ArrayList<>();
        buildMenuDetails2(toList, configTrees);
        if (roleId != null && CollUtil.isNotEmpty(relations)) {
            // 查询当前角色的菜单配置
            configTrees.forEach(item -> {
                boolean anyMatch = relations.stream().anyMatch(relation -> relation.getRoleMenuConfigId().equals(item.getId()));
                if (anyMatch) {
                    item.setIsChecked(true);
                }
            });
        }
        List<SumTree<FtbPermissionMenuConfigTree>> trees = TreeDotUtils.convertListToTreeDot(configTrees);
        List<FtbPermissionMenuConfigTreeVO> jsonToList = JsonUtil.getJsonToList(trees, FtbPermissionMenuConfigTreeVO.class);
        return jsonToList;
    }

    /**
     * 查询子集
     * @param meuId
     * @param tenantId
     * @param data
     */
    private void getTreeMenuWithPreantId(String meuId, String tenantId,List<ModuleEntity> data){
        List<ModuleBakUpEntity> moduleEntityList = moduleApi.findAllSubsetsBasedOnParentBakUp(meuId,tenantId);
        if (CollUtil.isNotEmpty(moduleEntityList)){
            List<ModuleEntity> moduleEntities = moduleEntityList.stream().map(ModuleBakUpEntity::convert).collect(Collectors.toList());
            data.addAll(moduleEntities);
            moduleEntityList.forEach(vo->{
                getTreeMenuWithPreantId(vo.getId(),tenantId,data);
            });
        }
    }


    private void getTreeMenuWithPreantId2(String meuId, String tenantId, List<ModuleEntity> data) {
        List<ModuleEntity> moduleEntityList = moduleApi.findAllSubsetsBasedOnParent(meuId,tenantId);
        if (CollUtil.isNotEmpty(moduleEntityList)){
            data.addAll(moduleEntityList);
            moduleEntityList.forEach(vo->{
                getTreeMenuWithPreantId2(vo.getId(),tenantId,data);
            });
        }
    }
    public void buildMenuDetails2(List<MenuListVO> newData, List<FtbPermissionMenuConfigTree> list){
        for (MenuListVO moduleEntity : newData) {
            String id = moduleEntity.getId();
            FtbPermissionMenuConfigTree configTree = new FtbPermissionMenuConfigTree();
            configTree.setId(id);
            configTree.setName(moduleEntity.getFullName());
            configTree.setParentId(moduleEntity.getParentId());
            configTree.setModuleType(moduleEntity.getType());
            list.add(configTree);
            // 查询当前菜单是否配置了子页面
            LambdaQueryWrapper<FtbPermissionFunctionMenu> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(FtbPermissionFunctionMenu::getFunType,0);
            queryWrapper.eq(FtbPermissionFunctionMenu::getParentId,id);
            List<FtbPermissionFunctionMenu> functionMenuList = ftbPermissionFunctionMenuMapper.selectList(queryWrapper);
            if (CollUtil.isNotEmpty(functionMenuList)){
                // 查询当前菜单是否有子集
                list.addAll(functionMenuList.stream().map(FtbPermissionMenuConfigTree::convert).collect(Collectors.toList()));
                for (FtbPermissionFunctionMenu functionMenu : functionMenuList) {
                    LambdaQueryWrapper<FtbPermissionFunctionMenu> menuLambdaQueryWrapper = Wrappers.lambdaQuery();
                    menuLambdaQueryWrapper.eq(FtbPermissionFunctionMenu::getFunType,1);
                    menuLambdaQueryWrapper.eq(FtbPermissionFunctionMenu::getParentId,functionMenu.getId());
                    List<FtbPermissionFunctionMenu> buttonList = ftbPermissionFunctionMenuMapper.selectList(menuLambdaQueryWrapper);
                    if (CollUtil.isNotEmpty(buttonList)){
                        list.addAll(buttonList.stream().map(FtbPermissionMenuConfigTree::convert).collect(Collectors.toList()));
                    }
                }
            }else if (moduleEntity.getChildren() != null){
                // 子集递归
                List<MenuListVO> children = moduleEntity.getChildren();
                buildMenuDetails2(children, list);
            }
        }

    }
    private void buildMenuDetails1(List<MenuListVO> newData, List<FtbPermissionMigrateRoleTree> list) {
        for (MenuListVO moduleEntity : newData) {
            String id = moduleEntity.getId();
            FtbPermissionMigrateRoleTree configTree = new FtbPermissionMigrateRoleTree();
            configTree.setId(id);
            configTree.setName(moduleEntity.getFullName());
            configTree.setParentId(moduleEntity.getParentId());
            configTree.setModuleType(1);
            list.add(configTree);
            // 查询当前菜单是否配置了按钮
            List<ModuleButtonEntity> buttonEntities = ftbPermissionMigrateMapper.inquiryButton(id);
            if (buttonEntities != null && !buttonEntities.isEmpty()) {
                List<FtbPermissionMigrateRoleTree> collected = buttonEntities.stream().map(v -> {
                    FtbPermissionMigrateRoleTree buttonTree = new FtbPermissionMigrateRoleTree();
                    buttonTree.setId(v.getId());
                    buttonTree.setName(v.getFullName());
                    buttonTree.setParentId(id);
                    buttonTree.setModuleType(2);
                    return buttonTree;
                }).collect(Collectors.toList());
                list.addAll(collected);
            }else if (moduleEntity.getChildren() != null){
                buildMenuDetails1(moduleEntity.getChildren(), list);
            }
        }
    }
    private List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> personnelMenu(List<String> userIds, Integer type) {
        List<String> authorities = ftbPermissionMigrateMapper.personnelMenuAuthorities(userIds);
        List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> ftbPermissionPositionMenuInnerVOS = ftbPermissionMigrateMapper.personnelMenu(type);
        if (CollUtil.isEmpty(authorities)) {
            return new ArrayList<>();
        }
        return recursivePermissions(ftbPermissionPositionMenuInnerVOS, "0", authorities);
    }


    /**
     * 递归权限
     */
    private List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> recursivePermissions(
            List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> ftbPersonnelsAuthoritysList,
            String parentId, List<String> includeMap) {
        List<FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO> result = new ArrayList<>();
        for (FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO authority : ftbPersonnelsAuthoritysList) {
            FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO permissionVO = new FtbPermissionPositionMenuVO.FtbPermissionPositionMenuInnerVO();
            permissionVO.setMenuId(authority.getMenuId());
            permissionVO.setMenuName(authority.getMenuName());
            permissionVO.setParentId(authority.getParentId());
            permissionVO.setChecked(includeMap != null && includeMap.contains(authority.getMenuId()));
            if (parentId.equals(permissionVO.getParentId())) {
                permissionVO.setChildrenList(recursivePermissions(ftbPersonnelsAuthoritysList, authority.getMenuId(), includeMap));
                result.add(permissionVO);
            }
        }
        return result;
    }

    private Integer convertScopePermission(Integer scopePermission) {
        // 根据这个数字0所在组织和下级组织员工,1所在组织员工,2仅下属，3指定组织 转换为-> 0全部1所在组织和下级组织员工,2所在组织员工,3仅下属,4指定组织
        switch (scopePermission) {
            case 0:
                return 1;
            case 1:
                return 2;
            case 2:
                return 3;
            case 3:
                return 4;
            default:
                return 0;
        }
    }

    public List<FtbPermissionMenuDirectoryVO> getAListOfMenuDirectory(String tenantId) {
        SystemEntity systemVO = systemApi.getSystemVO();
        String systemId = systemVO.getId();
        FtbPermissionRoleInfoVO vo = new FtbPermissionRoleInfoVO();
        List<ModuleEntity> data = moduleApi.getListWithoutSystemId(systemId, null, null, tenantId);
        // 获取顶级目录菜单
        List<ModuleEntity> entities = data.stream().filter(item -> item.getType() != null && item.getEnabledMark() != null && 1 == item.getEnabledMark() && "-1".equals(item.getParentId())).collect(Collectors.toList());
        List<FtbPermissionMenuDirectoryVO> directoryVOS = entities.stream().map(FtbPermissionMenuDirectoryVO::convert).distinct().collect(Collectors.toList());
        for (FtbPermissionMenuDirectoryVO directoryVO : directoryVOS) {
            List<FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO> infoVOS = entities.stream().filter(v -> v.getFullName().equals(directoryVO.getFullName())).map(v -> {
                FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO infoVO = new FtbPermissionMenuDirectoryVO.FtbPermissionMenuDirectoryInfoVO();
                String vCategory = v.getCategory();
                String vId = v.getId();
                infoVO.setId(vId);
                infoVO.setCategory(vCategory);
                return infoVO;
            }).collect(Collectors.toList());
            directoryVO.setChildren(infoVOS);
        }
        return directoryVOS.stream()
                .filter(item -> !EXCLUDED_DIRECTORIES.contains(item.getFullName()))
                .collect(Collectors.toList());
    }

    public static final Set<String> EXCLUDED_DIRECTORIES = Set.of(
            "资料库", "权限管理", "组织架构管理"
    );

}
