package jnpf.authority.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.fantaibao.permission.enums.FtbPermissionRedisKeys;
import jnpf.authority.mapper.*;
import jnpf.authority.service.FtbPermissionRoleService;
import jnpf.base.ActionResult;
import jnpf.base.ModuleApi;
import jnpf.base.SystemApi;
import jnpf.base.UserInfo;
import jnpf.base.entity.ModuleEntity;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.base.entity.SystemEntity;
import jnpf.model.authority.dto.menu.FtbPermissionRoleAddDTO;
import jnpf.model.authority.dto.role.FtbPermissionDataDTO;
import jnpf.model.authority.dto.role.FtbPermissionRoleCopyDTO;
import jnpf.model.authority.dto.role.FtbPermissionRoleInfoDTO;
import jnpf.model.authority.dto.role.FtbPermissionRoleUpdateDTO;
import jnpf.model.authority.po.*;
import jnpf.model.authority.vo.role.FtbPermissionRoleDetailsVO;
import jnpf.model.authority.vo.role.FtbPermissionRoleIdentificationVO;
import jnpf.model.authority.vo.role.FtbPermissionRoleInfoVO;
import jnpf.model.authority.vo.role.FtbPermissionRolePersonVO;
import jnpf.permission.V2UserApi;
import jnpf.permission.dto.v2.user.QueryUserBatchDTO;
import jnpf.permission.vo.v2.user.UserBoundVO;
import jnpf.util.UserProvider;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 *
 *
 *@Author: peng.hao
 *@create: 2025/3/5
 *
 */
@Service
public class FtbPermissionRoleServiceImpl extends ServiceImpl<FtbPermissionRoleMapper, FtbPermissionRole> implements FtbPermissionRoleService {

    @Resource
    private FtbPermissionRoleMapper ftbPermissionRoleMapper;

    @Resource
    private FtbPermissionRoleMenuMapper ftbPermissionRoleMenuMapper;

    @Resource
    private FtbPermissionRoleMenuRelationMapper ftbPermissionRoleMenuRelationMapper;

    @Resource
    private FtbPermissionRoleAuthorizePersonMapper ftbPermissionRoleAuthorizePersonMapper;

    @Resource
    private FtbPermissionRoleAuthorizePostMapper ftbPermissionRoleAuthorizePostMapper;

    @Resource
    private SystemApi systemApi;

    @Resource
    private ModuleApi moduleApi;

    @Resource
    private V2UserApi v2UserApi;

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public Page<FtbPermissionRoleInfoVO> permissionList(Page<FtbPermissionRoleInfoVO> page, FtbPermissionRoleInfoDTO roleInfoDTO) {
        if (StrUtil.isNotBlank(roleInfoDTO.getModuleIds())) {
            roleInfoDTO.setInnerModuleIds(Arrays.stream(roleInfoDTO.getModuleIds().split(",")).collect(Collectors.toList()));
        }
        Page<FtbPermissionRoleInfoVO> pages = ftbPermissionRoleMapper.permissionList(page, roleInfoDTO);
        if (CollUtil.isNotEmpty(roleInfoDTO.getInnerModuleIds())) {
            pages.getRecords().forEach(a -> {
                LambdaQueryWrapper<FtbPermissionRoleMenu> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(FtbPermissionRoleMenu::getRoleId, a.getRoleId());
                queryWrapper.eq(FtbPermissionRoleMenu::getRoleEnabled, 1);
                List<FtbPermissionRoleMenu> ftbPermissionRoleMenus = ftbPermissionRoleMenuMapper.selectList(queryWrapper);
                String functionWebId = ftbPermissionRoleMenus.stream().map(FtbPermissionRoleMenu::getFunctionWebId).collect(Collectors.joining(","));
                String functionAppId = ftbPermissionRoleMenus.stream().map(FtbPermissionRoleMenu::getFunctionAppId).collect(Collectors.joining(","));
                String functionPcId = ftbPermissionRoleMenus.stream().map(FtbPermissionRoleMenu::getFunctionPcId).collect(Collectors.joining(","));
                a.setFunctionWebId(functionWebId);
                a.setFunctionAppId(functionAppId);
                a.setFunctionPcId(functionPcId);
            });
        }
        SystemEntity systemVO = systemApi.getSystemVO();
        String systemId = systemVO.getId();
        String tenantId = UserProvider.getUser().getTenantId();
        List<ModuleEntity> data = moduleApi.getListWithoutSystemId(systemId, null, null, tenantId);
        // 获取顶级目录菜单
        if (data == null) {
            throw new RuntimeException("system服务异常，无法远程获取系统菜单");
        }
        List<ModuleEntity> entities = data.stream().filter(item -> item.getType() != null && item.getEnabledMark() != null && 1 == item.getEnabledMark() && "-1".equals(item.getParentId())).collect(Collectors.toList());
        pages.getRecords().forEach(a -> {
            if (a.getIsSuperAdmin() == 1) {
                a.setManageModule("全部");
            } else {
                // 拼接并过滤非空字段
                Stream<String> stream = Stream.empty();
                if (StrUtil.isNotBlank(a.getFunctionWebId())) {
                    stream = Arrays.stream(a.getFunctionWebId().split(","));
                }
                if (StrUtil.isNotBlank(a.getFunctionAppId())) {
                    stream = Stream.concat(stream, Arrays.stream(a.getFunctionAppId().split(",")));
                }
                if (StrUtil.isNotBlank(a.getFunctionPcId())) {
                    stream = Stream.concat(stream, Arrays.stream(a.getFunctionPcId().split(",")));
                }
                List<String> functionIds = stream
                        .filter(StrUtil::isNotBlank)
                        .collect(Collectors.toList());
                String manageModule = entities.stream()
                        .filter(item -> functionIds.contains(item.getId()))
                        .map(ModuleEntity::getFullName)
                        .distinct()
                        .collect(Collectors.joining("、"));
                a.setManageModule(manageModule);
            }
        });
        return pages;
    }

    @Override
    @Transactional
    public void addRole(FtbPermissionRoleAddDTO ftbPermissionRoleAddDTO) {
        // 角色名称不能重复
        LambdaQueryWrapper<FtbPermissionRole> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPermissionRole::getRoleName, ftbPermissionRoleAddDTO.getRoleName());
        queryWrapper.eq(FtbPermissionRole::getEnableMark, 0);
        if (ftbPermissionRoleMapper.selectCount(queryWrapper) > 0) {
            throw new RuntimeException("角色名称不可重复!");
        }
        FtbPermissionRole ftbPermissionRole = ftbPermissionRoleAddDTO.convertFtbPermissionRole(ftbPermissionRoleAddDTO);
        ftbPermissionRoleMapper.insert(ftbPermissionRole);
        fillRoleInfo(ftbPermissionRoleAddDTO.getPermissionRoleInners(), ftbPermissionRole.getId());
    }

    @Override
    @Transactional
    public void editRole(FtbPermissionRoleUpdateDTO roleUpdateDTO) {
        if ("1".equals(roleUpdateDTO.getRoleId())) {
            throw new RuntimeException("不能修改超级管理员角色!");
        }
        // 角色名称不能重复
        LambdaQueryWrapper<FtbPermissionRole> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.ne(SuperBaseEntity.SuperIBaseEntity::getId, roleUpdateDTO.getRoleId());
        queryWrapper.eq(FtbPermissionRole::getRoleName, roleUpdateDTO.getRoleName());
        queryWrapper.eq(FtbPermissionRole::getEnableMark, 0);
        if (ftbPermissionRoleMapper.selectCount(queryWrapper) > 0) {
            throw new RuntimeException("角色名称不可重复!");
        }
        LambdaUpdateWrapper<FtbPermissionRole> updateWrapper = roleUpdateDTO.update(roleUpdateDTO);
        ftbPermissionRoleMapper.update(new FtbPermissionRole(), updateWrapper);
        // 删除历史旧有的数据
        if (CollUtil.isNotEmpty(roleUpdateDTO.getPermissionRoleInners())) {
            roleUpdateDTO.getPermissionRoleInners().forEach(a -> {
                LambdaQueryWrapper<FtbPermissionRoleMenu> deleteWrapper = new LambdaQueryWrapper<FtbPermissionRoleMenu>()
                        .select(FtbPermissionRoleMenu::getId)
                        .eq(FtbPermissionRoleMenu::getRoleId, roleUpdateDTO.getRoleId());
                if (StrUtil.isNotBlank(a.getFunctionWebId()) && StrUtil.isNotBlank(a.getFunctionAppId()) && StrUtil.isNotBlank(a.getFunctionPcId())) {
                    // 组装or语句
                    deleteWrapper.and(b -> {
                        b.eq(FtbPermissionRoleMenu::getFunctionWebId, a.getFunctionWebId());
                        b.or();
                        b.eq(FtbPermissionRoleMenu::getFunctionAppId, a.getFunctionAppId());
                        b.or();
                        b.eq(FtbPermissionRoleMenu::getFunctionPcId, a.getFunctionPcId());
                    });
                } else {
                    if (StrUtil.isNotBlank(a.getFunctionWebId())) {
                        deleteWrapper.eq(FtbPermissionRoleMenu::getFunctionWebId, a.getFunctionWebId());
                    }
                    if (StrUtil.isNotBlank(a.getFunctionAppId())) {
                        deleteWrapper.eq(FtbPermissionRoleMenu::getFunctionAppId, a.getFunctionAppId());
                    }
                    if (StrUtil.isNotBlank(a.getFunctionPcId())) {
                        deleteWrapper.eq(FtbPermissionRoleMenu::getFunctionPcId, a.getFunctionPcId());
                    }
                }
                List<FtbPermissionRoleMenu> ftbPermissionRoleMenu = ftbPermissionRoleMenuMapper.selectList(deleteWrapper);
                if (CollUtil.isNotEmpty(ftbPermissionRoleMenu)) {
                    List<String> roleMenuIds = ftbPermissionRoleMenu.stream().map(FtbPermissionRoleMenu::getId).collect(Collectors.toList());
                    LambdaQueryWrapper<FtbPermissionRoleMenuRelation> deleteRoleWrapper = new LambdaQueryWrapper<FtbPermissionRoleMenuRelation>()
                            .eq(FtbPermissionRoleMenuRelation::getRoleId, roleUpdateDTO.getRoleId())
                            .in(FtbPermissionRoleMenuRelation::getRoleMenuId, roleMenuIds);
                    ftbPermissionRoleMenuMapper.delete(deleteWrapper);
                    ftbPermissionRoleMenuRelationMapper.delete(deleteRoleWrapper);
                }
            });
        }
        fillRoleInfo(roleUpdateDTO.getPermissionRoleInners(), roleUpdateDTO.getRoleId());
        // 角色绑定人员踢出下线
        personnelKickedOffTheLine(roleUpdateDTO.getRoleId());
    }

    private void fillRoleInfo(List<FtbPermissionRoleAddDTO.PermissionRoleInnerDTO> permissionRoleInners, String roleId) {
        if (CollUtil.isNotEmpty(permissionRoleInners)) {
            // 权限管理角色菜单
            permissionRoleInners.stream()
                    .filter(a -> CollUtil.isNotEmpty(a.getMemberIds()))
                    .forEach(a -> {
                        FtbPermissionRoleMenu ftbPermissionRoleMenu = a.convert(a);
                        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);
                    });
        }
    }

    @Override
    @Transactional
    public void deleteRole(String id) {
        if ("1".equals(id)) {
            throw new RuntimeException("不能删除超级管理员角色!");
        }
        // 角色绑定人员踢出下线
        personnelKickedOffTheLine(id);
        // 根据角色id删除角色菜单
        LambdaUpdateWrapper<FtbPermissionRole> a = new LambdaUpdateWrapper<>();
        a.eq(SuperBaseEntity.SuperIBaseEntity::getId, id);
        a.set(FtbPermissionRole::getEnableMark,1);
        ftbPermissionRoleMapper.update(new FtbPermissionRole(), a);
        // 根据角色id删除角色功能关联
        LambdaUpdateWrapper<FtbPermissionRoleMenuRelation> b = new LambdaUpdateWrapper<>();
        b.eq(FtbPermissionRoleMenuRelation::getRoleId, id);
        b.set(FtbPermissionRoleMenuRelation::getEnableMark,1);
        ftbPermissionRoleMenuRelationMapper.update(new FtbPermissionRoleMenuRelation(),b);
        // 根据角色id删除角色菜单关联
        LambdaUpdateWrapper<FtbPermissionRoleMenu> c = new LambdaUpdateWrapper<>();
        c.eq(FtbPermissionRoleMenu::getRoleId, id);
        c.set(FtbPermissionRoleMenu::getEnableMark,1);
        ftbPermissionRoleMenuMapper.update(new FtbPermissionRoleMenu(),c);
        // 根据角色id删除权限管理角色人员授权
        LambdaUpdateWrapper<FtbPermissionRoleAuthorizePerson> d = new LambdaUpdateWrapper<>();
        d.eq(FtbPermissionRoleAuthorizePerson::getRoleId, id);
        d.set(FtbPermissionRoleAuthorizePerson::getEnableMark,1);
        ftbPermissionRoleAuthorizePersonMapper.update(new FtbPermissionRoleAuthorizePerson(),d);
        // 根据角色id删除权限管理角色岗位授权
        LambdaUpdateWrapper<FtbPermissionRoleAuthorizePost> e = new LambdaUpdateWrapper<>();
        e.eq(FtbPermissionRoleAuthorizePost::getRoleId, id);
        e.set(FtbPermissionRoleAuthorizePost::getEnableMark,1);
        ftbPermissionRoleAuthorizePostMapper.update(new FtbPermissionRoleAuthorizePost(),e);
    }

    @Override
    public FtbPermissionRoleIdentificationVO permissionIdentificationCollection() {
        UserInfo userInfo = UserProvider.getUser();
        FtbPermissionRoleIdentificationVO ftbPermissionRoleIdentificationVO = new FtbPermissionRoleIdentificationVO();
        if (userInfo.getIsAdministrator()) {
            ftbPermissionRoleIdentificationVO.setIsSuperAdmin(1);
            return ftbPermissionRoleIdentificationVO;
        } else {
            ftbPermissionRoleIdentificationVO.setIsSuperAdmin(0);
        }
        // 当前人员权限
        List<String> permissionIdentifications = ftbPermissionRoleMapper.permissionIdentifications(userInfo.getUserId());
        // 获取人员岗位并获取岗位权限
        ActionResult<List<UserBoundVO>> userPrimaryBoundBatch = v2UserApi.getUserPrimaryBoundBatch(List.of(userInfo.getUserId()), null);
        if (userPrimaryBoundBatch.getCode() == 200 && !userPrimaryBoundBatch.getData().isEmpty()) {
            String positionId = userPrimaryBoundBatch.getData().get(0).getPositionId();
            List<String> jobPermissions = ftbPermissionRoleMapper.queryJobPermissions(positionId);
            permissionIdentifications = Stream.concat(permissionIdentifications.stream(), jobPermissions.stream())
                    .distinct()
                    .collect(Collectors.toList());
        }
        ftbPermissionRoleIdentificationVO.setPermissionIdentifications(permissionIdentifications);
        return ftbPermissionRoleIdentificationVO;
    }

    @Override
    public FtbPermissionRoleDetailsVO roleDetails(String roleId, String menuWebId, String menuAppId, String menuPcId) {
        FtbPermissionRoleDetailsVO ftbPermissionRoleDetails = new FtbPermissionRoleDetailsVO();
        LambdaQueryWrapper<FtbPermissionRoleMenu> queryWrapper = new LambdaQueryWrapper<FtbPermissionRoleMenu>()
                .eq(FtbPermissionRoleMenu::getRoleId, roleId);
        if (StrUtil.isNotBlank(menuAppId) && StrUtil.isNotBlank(menuWebId) && StrUtil.isNotBlank(menuPcId)) {
            // 组装or语句
            queryWrapper.and(a -> {
                a.eq(FtbPermissionRoleMenu::getFunctionWebId, menuWebId);
                a.or();
                a.eq(FtbPermissionRoleMenu::getFunctionAppId, menuAppId);
                a.or();
                a.eq(FtbPermissionRoleMenu::getFunctionPcId, menuPcId);
            });
        } else {
            if (StrUtil.isNotBlank(menuWebId)) {
                queryWrapper.eq(FtbPermissionRoleMenu::getFunctionWebId, menuWebId);
            }
            if (StrUtil.isNotBlank(menuAppId)) {
                queryWrapper.eq(FtbPermissionRoleMenu::getFunctionAppId, menuAppId);
            }
            if (StrUtil.isNotBlank(menuPcId)) {
                queryWrapper.eq(FtbPermissionRoleMenu::getFunctionPcId, menuPcId);
            }
        }
        queryWrapper.orderByDesc(FtbPermissionRoleMenu::getCreatorTime);
        queryWrapper.last("limit 1");
        FtbPermissionRoleMenu ftbPermissionRoleMenus = ftbPermissionRoleMenuMapper.selectOne(queryWrapper);
        if (ftbPermissionRoleMenus == null) {
            return ftbPermissionRoleDetails;
        }
        ftbPermissionRoleDetails.setRoleEnabled(ftbPermissionRoleMenus.getRoleEnabled());
        ftbPermissionRoleDetails.setScopePermission(ftbPermissionRoleMenus.getScopePermission());
        ftbPermissionRoleDetails.setSpecifyOrgIds(ftbPermissionRoleMenus.getSpecifyOrgIds());
        ftbPermissionRoleDetails.setFunctionPageWebId(ftbPermissionRoleMenus.getFunctionPageWebId());
        ftbPermissionRoleDetails.setFunctionPageAppId(ftbPermissionRoleMenus.getFunctionPageAppId());
        ftbPermissionRoleDetails.setFunctionPagePcId(ftbPermissionRoleMenus.getFunctionPagePcId());
        // 已勾选的菜单Id集合
        List<String> memberIds = ftbPermissionRoleMenuRelationMapper.selectList(new LambdaQueryWrapper<FtbPermissionRoleMenuRelation>()
                        .eq(FtbPermissionRoleMenuRelation::getRoleMenuId, ftbPermissionRoleMenus.getId()))
                .stream()
                .map(FtbPermissionRoleMenuRelation::getRoleMenuConfigId)
                .collect(Collectors.toList());
        ftbPermissionRoleDetails.setMemberIds(memberIds);
        return ftbPermissionRoleDetails;
    }

    // 定义权限优先级映射
    private static final Map<Integer, Integer> SCOPE_PRIORITY_MAP = new HashMap<>();

    static {
        // 权限适用范围,0全部1所在组织和下级组织员工,2所在组织员工,3仅下属,4指定组织
        // 数据权限优先级为：全部>指定权限>所属组织及下级组织员工>所在组织员工>仅下属
        SCOPE_PRIORITY_MAP.put(0, 0);
        SCOPE_PRIORITY_MAP.put(4, 1);
        SCOPE_PRIORITY_MAP.put(1, 2);
        SCOPE_PRIORITY_MAP.put(2, 3);
        SCOPE_PRIORITY_MAP.put(3, 4);
    }

    @Override
    public Map<String, String> queryUserScopeOfPermission(String userId,String... tenantIds) {
        String tenantId = tenantIds.length > 0 ? tenantIds[0] : UserProvider.getUser().getTenantId();
        return doQueryUserScopeOfPermission(userId, tenantId, false);
    }

    @Override
    public Map<String, String> queryUserScopeOfPermissionNoTenant(String userId) {
        String tenantId = UserProvider.getUser().getTenantId();
        return doQueryUserScopeOfPermission(userId, tenantId, true);
    }

    /**
     * 查询用户权限范围（公共方法）
     *
     * @param userId              用户ID
     * @param tenantId            租户ID
     * @param refreshMenuPermission 是否刷新Redis菜单权限缓存
     * @return 用户权限范围Map
     */
    private Map<String, String> doQueryUserScopeOfPermission(String userId, String tenantId, boolean refreshMenuPermission) {
        // 获取人员岗位并获取岗位权限
        ActionResult<List<UserBoundVO>> userPrimaryBoundBatch = v2UserApi.getUserPrimaryBoundBatch(List.of(userId), tenantId);
        if (userPrimaryBoundBatch.getCode() != 200 && (userPrimaryBoundBatch.getData() == null || userPrimaryBoundBatch.getData().isEmpty())) {
            throw new RuntimeException("获取用户主岗信息失败");
        }
        String positionId = userPrimaryBoundBatch.getData().get(0).getPositionId();
        // 用户授权信息
        List<FtbPermissionRolePersonVO> ftbPermissionRolePersonVOS = ftbPermissionRoleAuthorizePersonMapper.queryUserScopeOfPermission(userId);
        Map<String, String> first = new HashMap<>(ftbPermissionRolePersonVOS.size() * 2);
        populateMap(ftbPermissionRolePersonVOS, first);
        // 岗位授权信息
        List<FtbPermissionRolePersonVO> jobAuthorizationInformation = ftbPermissionRoleAuthorizePersonMapper.jobAuthorizationInformation(positionId);
        Map<String, String> second = new HashMap<>(jobAuthorizationInformation.size() * 2);
        populateMap(jobAuthorizationInformation, second);
        // 刷新用户菜单权限缓存到Redis
        if (refreshMenuPermission) {
            userMenuPermissions(userId, ftbPermissionRolePersonVOS, jobAuthorizationInformation);
        }
        // 整合web和app的权限
        Map<String, String> resultMaps = mergePermissions(first, second);
        // 员工个人特殊权限
        List<FtbPermissionRolePersonVO> peopleDataPermissions = ftbPermissionRoleAuthorizePersonMapper.getPeopleDataPermissions(userId);
        // 无角色但是已配置了个人特殊权限，只有一种情况，之前绑定了角色但是又删除了
        if (resultMaps.isEmpty() && CollUtil.isNotEmpty(peopleDataPermissions)) {
            return resultMaps;
        }
        // 将特殊权限进行替换
        peopleDataPermissions.forEach(peopleDataPermission -> {
            String designateTheOrganization = buildScopeValue(peopleDataPermission);
            resultMaps.put(peopleDataPermission.getWebId(), designateTheOrganization);
            resultMaps.put(peopleDataPermission.getAppId(), designateTheOrganization);
        });
        return resultMaps;
    }
    @Override
    public Map<String, Map<String, String>> queryUserScopeOfPermission(List<String> userIds, String... tenantIds) {
        // 获取人员岗位并获取岗位权限
        String tenantId = tenantIds.length > 0 ? tenantIds[0] : UserProvider.getUser().getTenantId();
        ActionResult<List<UserBoundVO>> userPrimaryBoundBatch = v2UserApi.getUserPrimaryBoundBatch(userIds, tenantId);
        List<UserBoundVO> userPrimaryBoundBatchData = userPrimaryBoundBatch.getData();
        if(CollUtil.isEmpty(userPrimaryBoundBatchData)){
            throw new RuntimeException("获取用户主岗信息失败");
        }
        List<String> userIdsData = userPrimaryBoundBatchData.stream().map(UserBoundVO::getId).collect(Collectors.toList());

        List<String> positionIds =userPrimaryBoundBatchData.stream().map(UserBoundVO::getPositionId).collect(Collectors.toList()) ;
        // 用户授权信息
        List<FtbPermissionRolePersonVO> ftbPermissionRolePersonVOSDb = ftbPermissionRoleAuthorizePersonMapper.queryUserScopeOfPermissionWithUserIds(userIdsData);
        Map<String, List<FtbPermissionRolePersonVO>> userPermissionRolePersonVOS = ftbPermissionRolePersonVOSDb.stream().collect(Collectors.groupingBy(FtbPermissionRolePersonVO::getUserId));
        // 岗位授权信息
        List<FtbPermissionRolePersonVO> jobAuthorizationInformationListVO = ftbPermissionRoleAuthorizePersonMapper.jobAuthorizationInformationWithPositionIds(positionIds);
        Map<String, List<FtbPermissionRolePersonVO>> postUserListMap = jobAuthorizationInformationListVO.stream().collect(Collectors.groupingBy(FtbPermissionRolePersonVO::getPostId));
        // 员工个人特殊权限
        List<FtbPermissionRolePersonVO> peopleDataPermissions = ftbPermissionRoleAuthorizePersonMapper.getPeopleDataPermissionsWithUserIds(userIds);
        Map<String, List<FtbPermissionRolePersonVO>> peopleDataPermissionsListMap = peopleDataPermissions.stream().collect(Collectors.groupingBy(FtbPermissionRolePersonVO::getUserId));
        Map<String, Map<String, String>> hashMap = new HashMap<>();
        userPrimaryBoundBatchData.forEach(vo -> {
            String userId = vo.getId();
            Map<String, String> first = new HashMap<>();
            Map<String, String> second = new HashMap<>();
            if(userPermissionRolePersonVOS.containsKey(userId)) {
                List<FtbPermissionRolePersonVO> ftbPermissionRolePersonVOS = userPermissionRolePersonVOS.get(userId);
                populateMap(ftbPermissionRolePersonVOS, first);
            }
            if(postUserListMap.containsKey(vo.getPositionId())) {
                List<FtbPermissionRolePersonVO> permissionRolePersonVOS = postUserListMap.get(vo.getPositionId());
                populateMap(permissionRolePersonVOS, second);
            }
            // 整合web和app的权限
            Map<String, String> resultMaps = mergePermissions(first, second);
            if (!peopleDataPermissionsListMap.containsKey(userId)) {
                hashMap.put(userId, resultMaps);
                return;
            }
            List<FtbPermissionRolePersonVO> rolePersonVOS = peopleDataPermissionsListMap.get(userId);
            // 将特殊权限进行替换
            rolePersonVOS.forEach(peopleDataPermission -> {
                String designateTheOrganization = buildScopeValue(peopleDataPermission);
                resultMaps.put(peopleDataPermission.getWebId(), designateTheOrganization);
                resultMaps.put(peopleDataPermission.getAppId(), designateTheOrganization);
            });
            hashMap.put(userId, resultMaps);
        });
        return hashMap;
    }
    @Override
    public Set<String> queryTheLatestListOfMenuPermissions(String userId) {
        // 获取人员岗位并获取岗位权限
        ActionResult<List<UserBoundVO>> userPrimaryBoundBatch = v2UserApi.getUserPrimaryBoundBatch(List.of(userId), UserProvider.getUser().getTenantId());
        if (userPrimaryBoundBatch.getCode() != 200 && CollUtil.isEmpty(userPrimaryBoundBatch.getData())) {
            throw new RuntimeException("获取用户主岗信息失败");
        }
        if (CollUtil.isEmpty(userPrimaryBoundBatch.getData())) {
            throw new RuntimeException("获取用户信息失败");
        }
        String positionId = userPrimaryBoundBatch.getData().get(0).getPositionId();
        // 用户授权信息
        List<FtbPermissionRolePersonVO> ftbPermissionRolePersonVOS = ftbPermissionRoleAuthorizePersonMapper.queryUserScopeOfPermission(userId);
        Map<String, String> first = new HashMap<>(ftbPermissionRolePersonVOS.size() * 2);
        populateMap(ftbPermissionRolePersonVOS, first);
        // 岗位授权信息
        List<FtbPermissionRolePersonVO> jobAuthorizationInformation = ftbPermissionRoleAuthorizePersonMapper.jobAuthorizationInformation(positionId);
        Map<String, String> second = new HashMap<>(jobAuthorizationInformation.size() * 2);
        populateMap(jobAuthorizationInformation, second);
        // 用户菜单权限
        return userMenuPermissionsWithUserId(ftbPermissionRolePersonVOS, jobAuthorizationInformation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dataPermissionApplicationToOtherModules(FtbPermissionDataDTO ftbPermissionDataDTO) {
        if (CollUtil.isEmpty(ftbPermissionDataDTO.getFtbPermissionDataInnerDTOs())) {
            return;
        }
        LambdaUpdateWrapper<FtbPermissionRoleMenu> roleMenuLambdaUpdateWrapper = Wrappers.lambdaUpdate();
        roleMenuLambdaUpdateWrapper.eq(FtbPermissionRoleMenu::getRoleId, ftbPermissionDataDTO.getRoleId());
        roleMenuLambdaUpdateWrapper.set(FtbPermissionRoleMenu::getScopePermission, ftbPermissionDataDTO.getScopePermission());
        roleMenuLambdaUpdateWrapper.set(FtbPermissionRoleMenu::getSpecifyOrgIds, ftbPermissionDataDTO.getSpecifyOrgIds());
        List<String> webIds = ftbPermissionDataDTO.getFtbPermissionDataInnerDTOs()
                .stream()
                .map(FtbPermissionDataDTO.FtbPermissionDataInnerDTO::getFunctionWebId)
                .filter(StrUtil::isNotBlank).collect(Collectors.toList());
        List<String> appIds = ftbPermissionDataDTO.getFtbPermissionDataInnerDTOs()
                .stream()
                .map(FtbPermissionDataDTO.FtbPermissionDataInnerDTO::getFunctionAppId)
                .filter(StrUtil::isNotBlank).collect(Collectors.toList());
        List<String> pcIds = ftbPermissionDataDTO.getFtbPermissionDataInnerDTOs()
                .stream()
                .map(FtbPermissionDataDTO.FtbPermissionDataInnerDTO::getFunctionPcId)
                .filter(StrUtil::isNotBlank).collect(Collectors.toList());
        if (CollUtil.isEmpty(webIds) && CollUtil.isEmpty(appIds) && CollUtil.isEmpty(pcIds)) {
            return;
        }
        roleMenuLambdaUpdateWrapper.in(CollUtil.isNotEmpty(webIds),FtbPermissionRoleMenu::getFunctionWebId, webIds);
        roleMenuLambdaUpdateWrapper.in(CollUtil.isNotEmpty(appIds),FtbPermissionRoleMenu::getFunctionAppId, appIds);
        roleMenuLambdaUpdateWrapper.in(CollUtil.isNotEmpty(pcIds),FtbPermissionRoleMenu::getFunctionPcId, pcIds);
        ftbPermissionRoleMenuMapper.update(new FtbPermissionRoleMenu(), roleMenuLambdaUpdateWrapper);
    }



    @Override
    @Transactional
    public void copyRole(FtbPermissionRoleCopyDTO ftbPermissionRole) {
        LambdaQueryWrapper<FtbPermissionRoleMenu> roleMenuLambdaQueryWrapper = Wrappers.lambdaQuery();
        roleMenuLambdaQueryWrapper.eq(FtbPermissionRoleMenu::getRoleId, ftbPermissionRole.getRoleId());
        roleMenuLambdaQueryWrapper.eq(FtbPermissionRoleMenu::getEnableMark, 0);
        List<FtbPermissionRoleMenu> ftbPermissionRoleMenus = ftbPermissionRoleMenuMapper.selectList(roleMenuLambdaQueryWrapper);
        if (CollUtil.isNotEmpty(ftbPermissionRole.getPermissionRoleInners())) {
            List<String> webIds = ftbPermissionRole.getPermissionRoleInners().stream()
                    .flatMap(a -> Stream.of(a.getFunctionWebId(), a.getFunctionAppId(), a.getFunctionPcId()))
                    .filter(StrUtil::isNotBlank)
                    .collect(Collectors.toList());
            ftbPermissionRoleMenus = ftbPermissionRoleMenus.stream()
                    .filter(a -> Stream.of(a.getFunctionWebId(), a.getFunctionAppId(), a.getFunctionPcId())
                            .filter(StrUtil::isNotBlank)
                            .noneMatch(webIds::contains))
                    .collect(Collectors.toList());
        }
        ftbPermissionRoleMenus.forEach(a -> {
            FtbPermissionRoleAddDTO.PermissionRoleInnerDTO permissionRoleInnerDTO = new FtbPermissionRoleAddDTO.PermissionRoleInnerDTO();
            permissionRoleInnerDTO.setRoleEnabled(a.getRoleEnabled());
            permissionRoleInnerDTO.setFunctionWebId(a.getFunctionWebId());
            permissionRoleInnerDTO.setFunctionAppId(a.getFunctionAppId());
            permissionRoleInnerDTO.setFunctionPcId(a.getFunctionPcId());
            permissionRoleInnerDTO.setScopePermission(a.getScopePermission());
            permissionRoleInnerDTO.setSpecifyOrgIds(a.getSpecifyOrgIds());
            permissionRoleInnerDTO.setFunctionPageAppId(a.getFunctionPageAppId());
            permissionRoleInnerDTO.setFunctionPageWebId(a.getFunctionPageWebId());
            permissionRoleInnerDTO.setFunctionPagePcId(a.getFunctionPagePcId());
            // 功能菜单及子页面主键id集合
            LambdaQueryWrapper<FtbPermissionRoleMenuRelation> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.select(FtbPermissionRoleMenuRelation::getRoleMenuConfigId);
            queryWrapper.eq(FtbPermissionRoleMenuRelation::getRoleId, ftbPermissionRole.getRoleId());
            queryWrapper.eq(FtbPermissionRoleMenuRelation::getRoleMenuId, a.getId());
            List<FtbPermissionRoleMenuRelation> ftbPermissionRoleMenuRelations = ftbPermissionRoleMenuRelationMapper.selectList(queryWrapper);
            if (CollUtil.isNotEmpty(ftbPermissionRoleMenuRelations)) {
                List<String> roleMenuConfigs = ftbPermissionRoleMenuRelations.stream().map(FtbPermissionRoleMenuRelation::getRoleMenuConfigId).collect(Collectors.toList());
                permissionRoleInnerDTO.setMemberIds(roleMenuConfigs);
            }
            ftbPermissionRole.getPermissionRoleInners().add(permissionRoleInnerDTO);
        });
        // 添加角色
        addRole(ftbPermissionRole);
    }


    private void userMenuPermissions(String userId, List<FtbPermissionRolePersonVO> ftbPermissionRolePersonVOS, List<FtbPermissionRolePersonVO> jobAuthorizationInformation) {
        Set<String> result = new HashSet<>();
        Stream.concat(ftbPermissionRolePersonVOS.stream(), jobAuthorizationInformation.stream())
                .forEach(a -> {
                    Stream.of(a.getFunctionPageAppId(), a.getFunctionPageWebId(), a.getWebId()
                                    , a.getAppId(), a.getPcId(),a.getFunctionPagePcId())
                            .filter(StrUtil::isNotBlank)
                            .flatMap(b -> Arrays.stream(b.split(StringPool.COMMA)))
                            .forEach(result::add);
                });
        // 存放Redis，获取用户信息时使用
        redisTemplate.opsForValue().set("user:permission:menu:" + userId, String.join(",", result));
        // 查询权限编码并存入redis
        List<String> roleMenuIds = Stream.concat(ftbPermissionRolePersonVOS.stream(), jobAuthorizationInformation.stream())
                .map(FtbPermissionRolePersonVO::getRoleMenuId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(roleMenuIds)) {
            // 查询权限编码并存入redis
            List<String> funcCodings = ftbPermissionRoleMenuMapper.queryFuncCodingsByRoleMenuIds(roleMenuIds);
            if (CollUtil.isNotEmpty(funcCodings)) {
                redisTemplate.opsForValue().set(FtbPermissionRedisKeys.PERMISSION_ENCODING_KEY  + userId, String.join(",", funcCodings));
            }
        }
    }

    private Set<String> userMenuPermissionsWithUserId(List<FtbPermissionRolePersonVO> ftbPermissionRolePersonVOS, List<FtbPermissionRolePersonVO> jobAuthorizationInformation) {
        Set<String>  result = new HashSet<>();
        Stream.concat(ftbPermissionRolePersonVOS.stream(), jobAuthorizationInformation.stream())
                .forEach(a -> {
                    Stream.of(a.getFunctionPageAppId(), a.getFunctionPageWebId(), a.getWebId(), a.getAppId())
                            .filter(StrUtil::isNotBlank)
                            .flatMap(b -> Arrays.stream(b.split(StringPool.COMMA)))
                            .forEach(result::add);
                });
        // 存放Redis，获取用户信息时使用
        return  result;
    }

    // 合并权限方法
    private Map<String, String> mergePermissions(Map<String, String> first, Map<String, String> second) {
        // 确定主从集合：较大的作为基础，较小的用于更新
        Map<String, String> base = first.size() > second.size() ? first : second;
        Map<String, String> update = first.size() > second.size() ? second : first;
        // 初始化结果集
        Map<String, String> result = new HashMap<>(base);
        // 遍历更新集合并按优先级更新
        update.forEach((key, value) -> {
            if (result.containsKey(key)) {
                int currentPriority = getScopePriority(result.get(key));
                int newPriority = getScopePriority(value);
                if (newPriority < currentPriority) {
                    result.put(key, value);
                } else if (newPriority == currentPriority) {
                    // 优先级相同时，取并集
                    result.put(key, mergeScopeValues(result.get(key), value));
                }
            } else {
                result.put(key, value);
            }
        });
        return result;
    }

    // 获取权限优先级的方法
    private int getScopePriority(String scopeValue) {
        String[] parts = scopeValue.split("#");
        int scope = Integer.parseInt(parts[0]);
        // 如果没有匹配到，默认为最低优先级
        return SCOPE_PRIORITY_MAP.getOrDefault(scope, Integer.MAX_VALUE);
    }

    private void populateMap(List<FtbPermissionRolePersonVO> dataList, Map<String, String> targetMap) {
        // 过滤模块未设置数据权限的数据
        dataList.stream().filter(vo -> Objects.nonNull(vo.getScope())).forEach(vo ->
                Stream.of(vo.getWebId(), vo.getAppId(), vo.getPcId())
                        .filter(StrUtil::isNotBlank)
                        .forEach(key -> {
                            if (targetMap.containsKey(key)) {
                                // 如果已存在，则合并权限
                                String existingScopeValue = targetMap.get(key);
                                String newScopeValue = buildScopeValue(vo);
                                int existingPriority = getScopePriority(existingScopeValue);
                                int newPriority = getScopePriority(newScopeValue);
                                if (newPriority < existingPriority) {
                                    targetMap.put(key, buildScopeValue(vo));
                                } else if (newPriority == existingPriority) {
                                    // 优先级相同时，取并集
                                    targetMap.put(key, mergeScopeValues(existingScopeValue, newScopeValue));
                                }
                            } else {
                                targetMap.put(key, buildScopeValue(vo));
                            }
                        })
        );
    }

    private String mergeScopeValues(String existingValue, String newValue) {
        // 解析现有值和新值
        String[] existingParts = existingValue.split("#");
        String[] newParts = newValue.split("#");

        int existingScope = Integer.parseInt(existingParts[0]);
        int newScope = Integer.parseInt(newParts[0]);

        // 只有当权限范围类型相同时才合并（理论上这里existingScope == newScope）
        if (existingScope == newScope) {
            // 对于指定组织类型(4)需要合并组织ID
            if (existingScope == 4 && existingParts.length > 1 && newParts.length > 1) {
                // 合并组织ID列表，去重
                Set<String> orgIds = new HashSet<>();
                String[] existingOrgIds = existingParts[1].split(",");
                String[] newOrgIds = newParts[1].split(",");

                orgIds.addAll(Arrays.asList(existingOrgIds));
                orgIds.addAll(Arrays.asList(newOrgIds));

                return existingScope + "#" + String.join(",", orgIds);
            } else {
                // 对于其他类型，直接返回其中一个即可（因为它们是相同的）
                return existingValue;
            }
        }
        // 正常情况下不应该到达这里，但如果到达了，返回优先级更高的那个
        return getScopePriority(existingValue) <= getScopePriority(newValue) ? existingValue : newValue;
    }


    private String buildScopeValue(FtbPermissionRolePersonVO vo) {
        return vo.getScope() == 4 ?
                String.format("%d#%s", vo.getScope(), vo.getOrgIds()) :
                String.valueOf(vo.getScope());
    }


    /**
     * 人员被踢下线
     *
     * @param roleId 角色ID
     */
    private void personnelKickedOffTheLine(String roleId) {
        String tenantId = UserProvider.getUser().getTenantId();
        LambdaQueryWrapper<FtbPermissionRoleAuthorizePerson> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(FtbPermissionRoleAuthorizePerson::getUserId);
        queryWrapper.eq(FtbPermissionRoleAuthorizePerson::getEnableMark,0);
        queryWrapper.eq(FtbPermissionRoleAuthorizePerson::getRoleId, roleId);
        List<FtbPermissionRoleAuthorizePerson> ftbPermissionRoleAuthorizePeople = ftbPermissionRoleAuthorizePersonMapper.selectList(queryWrapper);
        List<String> userIds = ftbPermissionRoleAuthorizePeople.stream().map(FtbPermissionRoleAuthorizePerson::getUserId).collect(Collectors.toList());
        // 查询岗位绑定的权限
        LambdaQueryWrapper<FtbPermissionRoleAuthorizePost> queryWrapperPost = Wrappers.lambdaQuery();
        queryWrapperPost.select(FtbPermissionRoleAuthorizePost::getPostId);
        queryWrapperPost.eq(FtbPermissionRoleAuthorizePost::getEnableMark,0);
        queryWrapperPost.eq(FtbPermissionRoleAuthorizePost::getRoleId, roleId);
        List<FtbPermissionRoleAuthorizePost> ftbPermissionRoleAuthorizePosts = ftbPermissionRoleAuthorizePostMapper.selectList(queryWrapperPost);
        List<String> postIds = ftbPermissionRoleAuthorizePosts.stream().map(FtbPermissionRoleAuthorizePost::getPostId).collect(Collectors.toList());
        // 根据岗位查询岗位所绑定的人员
        if (CollUtil.isNotEmpty(postIds)) {
            QueryUserBatchDTO dto = new QueryUserBatchDTO();
            dto.setPositionIds(postIds);
            dto.setTenantId(tenantId);
            ActionResult<List<UserBoundVO>> userInfoBatch = v2UserApi.getUserInfoBatch(dto);
            if (userInfoBatch != null && userInfoBatch.getCode() == 200) {
                userIds.addAll(userInfoBatch.getData().stream().map(UserBoundVO::getId).collect(Collectors.toList()));
            }
        }
        userIds.forEach(a -> {
            UserProvider.kickoutByUserId(a, tenantId);
        });
    }

}
