package org.springblade.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springblade.common.constant.DictTypeEnum;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.DigestUtil;
import org.springblade.system.cache.DictCache;
import org.springblade.system.cache.ParamCache;
import org.springblade.system.convert.DeptConvert;
import org.springblade.system.convert.UserConvert;
import org.springblade.system.log.ComposeLogUtil;
import org.springblade.system.pojo.entity.*;
import org.springblade.system.pojo.enums.DataSync;
import org.springblade.system.pojo.enums.DeptCategory;
import org.springblade.system.pojo.vo.UserDeptIdsVO;
import org.springblade.system.service.*;
import org.springblade.system.util.DataSyncRecordUtils;
import org.springblade.thirdparty.oa.constant.OAConstant;
import org.springblade.thirdparty.oa.constant.OAConvertConstant;
import org.springblade.thirdparty.oa.feign.IOAClient;
import org.springblade.thirdparty.oa.pojo.response.OACompanyResponse;
import org.springblade.thirdparty.oa.pojo.response.OADepartmentResponse;
import org.springblade.thirdparty.oa.pojo.response.OAPersonResponse;
import org.springblade.thirdparty.oa.pojo.search.OACompanySearch;
import org.springblade.thirdparty.oa.pojo.search.OADepartmentSearch;
import org.springblade.thirdparty.oa.pojo.search.OAPersonSearch;
import org.springblade.thirdparty.oa.pojo.search.OASearch;
import org.springblade.thirdparty.oa.util.OAUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static org.springblade.common.constant.CommonConstant.*;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
import static org.springblade.core.cache.constant.CacheConstant.USER_CACHE;

/**
 * @author bfhuange
 * @date 2024/8/23
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class OASyncServiceImpl implements IOASyncService {
    /**
     *  用户表部门id最大长度
     */
    private static final int MAX_DEPT_ID_LENGTH = 2000;

    private final IOAClient oaClient;
    private final DeptConvert deptConvert;
    private final IDeptService deptService;
    private final IUserService userService;
    private final UserConvert userConvert;
    private final IUserDeptService userDeptService;
    private final IRoleService roleService;
    private final IMKPushService mkPushService;
    private final IDataSyncRecordService dataSyncRecordService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncCompanyAndDeptAndPushMK(boolean syncAll) {
        try {
            ComposeLogUtil.addLog(log);
            // 1. 同步公司和部门并记录
            Date startTime = this.syncAndRecord(DataSyncRecordUtils::createOAOrgFetch, queryStartTime -> {
                // 1. 同步公司
                this.syncCompany(queryStartTime);
                // 2. 同步部门
                this.syncDept(queryStartTime);
                // 2. 更新部门祖级列表
                deptService.updateAncestors(queryStartTime);
            }, syncAll);
            // 2. 推送mk
            mkPushService.pushOrgAndRecord(startTime);
        } finally {
            ComposeLogUtil.removeLastLog();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncPersonAndPushMK(boolean syncAll) {
        try {
            ComposeLogUtil.addLog(log);
            // 1. 同步人员并记录
            Date startTime = this.syncAndRecord(DataSyncRecordUtils::createOAPersonFetch, this::syncPerson, syncAll);
            // 2. 推送mk
            mkPushService.pushPersonAndRecord(startTime);
        } finally {
            ComposeLogUtil.removeLastLog();
        }
    }

    /**
     * 同步并记录
     *
     * @param recordSupplier 同步记录提供
     * @param syncHandler    同步处理器
     * @param syncAll 是否同步所有
     * @return
     */
    private Date syncAndRecord(Supplier<DataSyncRecord> recordSupplier, Consumer<Date> syncHandler, boolean syncAll) {
        // 创建记录
        DataSyncRecord record = recordSupplier.get();
        // 查询最新一条成功记录
        DataSyncRecord lastSuccessRecord = syncAll ? null : dataSyncRecordService.getLastSuccessRecord(record);
        // 同步所有，开始时间设置为null，否则最新成功记录的同步时间作为查询开始时间，第一次为null同步所有
        Date startTime = syncAll ? null : Optional.ofNullable(lastSuccessRecord)
                .map(DataSyncRecord::getSyncTime)
                .orElse(null);
        // 同步时间设置早一些，可能下次增量同步会多同步一些数据
        // 设置晚了，增量同步可能会漏同步数据
        record.setSyncTime(new Date());
        try {
            // 1. 同步处理
            syncHandler.accept(startTime);
        } catch (Exception e) {
            // 有异常，结果改成失败
            record.setResult(DataSync.Result.FAIL.name());
            throw e;
        } finally {
            // 新事务保存同步记录
            dataSyncRecordService.saveWithNewTransaction(record);
        }
        return startTime;
    }

    /**
     *  同步公司
     * @param startTime 查询开始时间
     */
    private void syncCompany(Date startTime) {
        // 未处理的数据
        List<Dept> notHandleList = new ArrayList<>();
        // 1. 设置查询参数
        OACompanySearch companySearch = new OACompanySearch();
        companySearch.setCurPage(1);
        if (startTime != null) {
            // 开始时间不为空，设置修改时间参数
            companySearch.setModified(DateUtil.format(startTime, DateUtil.PATTERN_DATETIME));
        }
        // 2. 分页查询并处理数据
        OAUtils.pageSyncHandler(companySearch, param -> oaClient.queryCompanyPage(new OASearch<>(param)), response -> {
            ComposeLogUtil.getLastLog().error("调用OA接口查询公司信息失败 {}", JSON.toJSONString(response));
            return new ServiceException("调用OA接口查询公司信息失败");
        }, 10000, ComposeLogUtil.getLastLog()::info).accept(list -> {
            // 处理数据
            List<Dept> deptList = handleCompany(list);
            notHandleList.addAll(deptList);
        });
        // 3. 未处理的数据
        if (CollectionUtil.isNotEmpty(notHandleList)) {
            ComposeLogUtil.getLastLog().warn("同步公司，还有未处理的数据：{}", JSON.toJSONString(notHandleList));
        }
        // 清除部门缓存
        CacheUtil.clear(SYS_CACHE);
        CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
    }

    /**
     *  同步部门
     * @param startTime 查询开始时间
     */
    private void syncDept(Date startTime) {
        String subCompanyIds = getSubCompanyIds();
        if (StringUtils.isEmpty(subCompanyIds)) {
            ComposeLogUtil.getLastLog().warn("未查询到子公司查询参数");
            return;
        }
        // 未处理的数据
        List<Dept> notHandleList = new ArrayList<>();
        // 1. 设置查询参数
        OADepartmentSearch departmentSearch = new OADepartmentSearch();
        departmentSearch.setCurPage(1);
        departmentSearch.setSubcompanyid1(subCompanyIds);
        if (startTime != null) {
            // 开始时间不为空，设置修改时间参数
            departmentSearch.setModified(DateUtil.format(startTime, DateUtil.PATTERN_DATETIME));
        }
        // 2. 分页查询并处理数据
        OAUtils.pageSyncHandler(departmentSearch, param -> oaClient.queryDepartmentPage(new OASearch<>(param)), response -> {
            ComposeLogUtil.getLastLog().error("调用OA接口查询部门信息失败 {}", JSON.toJSONString(response));
            return new ServiceException("调用OA接口查询部门信息失败");
        }, 10000, ComposeLogUtil.getLastLog()::info).accept(list -> {
            // 处理数据
            List<Dept> deptList = handleDept(list);
            notHandleList.addAll(deptList);
        });
        // 3. 未处理的数据
        if (CollectionUtil.isNotEmpty(notHandleList)) {
            ComposeLogUtil.getLastLog().warn("同步部门，还有未处理的数据：{}", JSON.toJSONString(notHandleList));
        }
        // 清除部门缓存
        CacheUtil.clear(SYS_CACHE);
        CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
    }

    /**
     *  同步人员
     * @param startTime 查询开始时间
     */
    private void syncPerson(Date startTime) {
        String subCompanyIds = getSubCompanyIds();
        if (StringUtils.isEmpty(subCompanyIds)) {
            ComposeLogUtil.getLastLog().warn("未查询到子公司查询参数");
            return;
        }
        // 1. 设置查询参数
        OAPersonSearch personSearch = new OAPersonSearch();
        personSearch.setCurPage(1);
        personSearch.setSubcompanyid1(subCompanyIds);
        if (startTime != null) {
            // 开始时间不为空，设置修改时间参数
            personSearch.setModified(DateUtil.format(startTime, DateUtil.PATTERN_DATETIME));
        }
        // 2. 分页查询并处理数据
        OAUtils.pageSyncHandler(personSearch, param -> oaClient.queryPersonPage(new OASearch<>(param)), response -> {
            ComposeLogUtil.getLastLog().error("调用OA接口查询人员信息失败 {}", JSON.toJSONString(response));
            return new ServiceException("调用OA接口查询人员信息失败");
        }, 10000, ComposeLogUtil.getLastLog()::info).accept(this::handlePerson);
        // 清除用户缓存
        CacheUtil.clear(USER_CACHE);
    }

    /**
     *  处理oa人员
     * @param oaPersons
     */
    private void handlePerson(List<OAPersonResponse> oaPersons) {
        if (CollectionUtil.isEmpty(oaPersons)) {
            // 数据为空，直接返回
            return;
        }
        // 根公司id
        String rootCompanyId = getRootCompanyId();
        if (rootCompanyId == null) {
            return;
        }
        // 根公司下要同步的部门id
        Set<String> rootCompanyDeptIds = getRootCompanyDeptIds(rootCompanyId);
        oaPersons = oaPersons.stream()
                // 公司不是根公司，或者部门在根公司下要同步的部门列表中
                .filter(oaPerson -> !rootCompanyId.equals(oaPerson.getSubcompanyid1()) || rootCompanyDeptIds.contains(oaPerson.getDepartmentid()))
                .toList();
        // 根据手机号转成set
        TreeSet<OAPersonResponse> oaPersonSet = CollectionUtil.toTreeSet(oaPersons, Comparator.comparing(OAPersonResponse::getMobile));
        // 默认密码
        String defaultPassword = DigestUtil.encrypt(ParamCache.getValue(DEFAULT_PARAM_PASSWORD));
        // 转换数据
        List<User> users = oaPersonSet.stream()
                // 只需要手机不为空的
                .filter(person -> StringUtils.isNotBlank(person.getMobile()))
                .map(person -> userConvert.person2user(person, defaultPassword))
                .toList();
        List<String> phones = users.stream()
                .map(User::getPhone)
                .filter(StringUtils::isNotBlank)
                .distinct()
                .toList();
        // 查询所有用户
        Map<String, Long> userMap = userService.list(Wrappers.<User>lambdaQuery()
                        //.eq(User::getIsDeleted, BladeConstant.DB_NOT_DELETED)
                        .in(User::getPhone, phones)
                ).stream()
                // 解密手机号
                .peek(userService::decryptPhone)
                .collect(Collectors.toMap(User::getPhone, User::getId, (a, b) -> b));
        // 数据库存在的所有用户id
        Set<Long> existsUserIds = new HashSet<>(userMap.values());
        users.forEach(user -> {
            if (userMap.containsKey(user.getPhone())) {
                // 根据手机号获取对应的用户id
                user.setId(userMap.get(user.getPhone()));
                // 清空密码，不修改密码
                user.setPassword(null);
            } else {
                // 没有就生成一个id
                user.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
                userService.encryptPhone(user);
                userMap.put(user.getPhone(), user.getId());
            }
        });

        // 不存在的新增
        List<User> addUsers = users.stream()
                .filter(user -> !existsUserIds.contains(user.getId()))
                .toList();
        if (CollectionUtil.isNotEmpty(addUsers)) {
            ComposeLogUtil.getLastLog().info("批量新增用户：{}", addUsers.size());
            userService.saveBatch(addUsers);
        }
        // 存在的修改
        List<User> updateUsers = users.stream()
                .filter(user -> existsUserIds.contains(user.getId()))
                .toList();
        if (CollectionUtil.isNotEmpty(updateUsers)) {
            ComposeLogUtil.getLastLog().info("批量修改用户：{}", updateUsers.size());
            userService.updateBatchById(updateUsers);
        }
        // 没有手机号的数据 = 手机号为空的数量
        long noPhoneNum = oaPersons.stream()
                .map(OAPersonResponse::getMobile)
                .filter(StringUtils::isBlank)
                .count();
        ComposeLogUtil.getLastLog().info("没有手机号的数据：{}", noPhoneNum);

        Map<String, Long> userDeptMap = userDeptService.list(Wrappers.<UserDept>lambdaQuery()
                        .in(UserDept::getUserId, userMap.values())
                ).stream()
                .collect(Collectors.toMap(this::getUserDeptKey, UserDept::getId, (a, b) -> b));
        // 数据库存在的所有用户部门id
        Set<Long> existsUserDeptIds = new HashSet<>(userDeptMap.values());

        List<UserDept> userDeptList = oaPersons.stream()
                // 只要包含用户手机号的
                .filter(oaPerson -> userMap.containsKey(oaPerson.getMobile()))
                .map(oaPerson -> userConvert.person2userDept(oaPerson, userMap))
                .toList();
        userDeptList.forEach(userDept -> {
            String userDeptKey = getUserDeptKey(userDept);
            if (userDeptMap.containsKey(userDeptKey)) {
                // 根据key获取用户部门id
                userDept.setId(userDeptMap.get(userDeptKey));
            } else {
                // 没有就生成一个id
                userDept.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
            }
        });
        // 不存在的新增
        List<UserDept> addList = userDeptList.stream()
                .filter(userDept -> !existsUserDeptIds.contains(userDept.getId()))
                .toList();
        if (CollectionUtil.isNotEmpty(addList)) {
            ComposeLogUtil.getLastLog().info("批量新增用户部门：{}", addList.size());
            userDeptService.saveBatch(addList);
        }
        // 存在的修改
        List<UserDept> updateList = userDeptList.stream()
                .filter(userDept -> existsUserDeptIds.contains(userDept.getId()))
                .toList();
        if (CollectionUtil.isNotEmpty(updateList)) {
            ComposeLogUtil.getLastLog().info("批量修改用户部门：{}", updateList.size());
            userDeptService.updateBatchById(updateList);
        }
        // 回写部门id到用户表
        Collection<Long> userIds = userMap.values();
        List<UserDeptIdsVO> list = userDeptService.queryUserDeptIds(userIds);
        // 查询没有角色的用户id
        Set<Long> noRoleUserIds = userService.list(Wrappers.<User>lambdaQuery()
                        .in(User::getId, userIds)
                        .isNull(User::getRoleId)
                ).stream()
                .map(User::getId)
                .collect(Collectors.toSet());
        // 获取默认角色id
        String defaultRoleId = getDefaultRoleId();
        List<User> updateUserParams = list.stream()
                // 过滤掉空部门id及长度超长的
                .filter(userDeptIds -> StringUtils.isNotBlank(userDeptIds.getDeptIds()) && userDeptIds.getDeptIds().length() <= MAX_DEPT_ID_LENGTH)
                .map(userDeptIds -> {
                    User user = new User();
                    user.setId(userDeptIds.getUserId());
                    user.setDeptId(userDeptIds.getDeptIds());
                    user.setDeptCodes(userDeptIds.getDeptCodes());
                    if (noRoleUserIds.contains(userDeptIds.getUserId())) {
                        user.setRoleId(defaultRoleId);
                    }
                    return user;
                }).toList();
        userService.updateBatchById(updateUserParams);
    }

    /**
     *  处理oa公司
     * @param oaCompanies
     * @return 未处理的数据
     */
    private List<Dept> handleCompany(List<OACompanyResponse> oaCompanies) {
        if (CollectionUtil.isEmpty(oaCompanies)) {
            // 数据为空，直接返回
            return Collections.emptyList();
        }
        // 获取需要的公司名称
        Set<String> companyNames = getCompanyNames();
        // 转换数据
        List<Dept> allParam = oaCompanies.stream()
                // 筛选只要需要的公司
                .filter(company -> companyNames.contains(company.getSubcompanyname()))
                .map(deptConvert::company2dept)
                .toList();

        // 查询数据库的部门，转换成map
        Map<String, Long> deptMap = getAllCompanyDeptMap();

        // 处理部门
        return handleDept(allParam, deptMap, DeptCategory.COMPANY);
    }

    /**
     *  处理oa部门
     * @param oaDepts
     * @return 未处理的数据
     */
    private List<Dept> handleDept(List<OADepartmentResponse> oaDepts) {
        if (CollectionUtil.isEmpty(oaDepts)) {
            // 数据为空，直接返回
            return Collections.emptyList();
        }
        // 查询所有公司的编码和id的map
        Map<String, Long> companyDeptMap = getAllCompanyDeptMap();
        // 根公司id
        String rootCompanyId = getRootCompanyId();
        if (rootCompanyId == null) {
            return Collections.emptyList();
        }
        // 根公司下要同步的部门名称
        Set<String> rootCompanyDeptNames = getRootCompanyDeptNames();
        // 转换数据
        List<Dept> allParam = oaDepts.stream()
                // 部门的公司不是根公司，或者部门名称在根公司下需要同步的部门列表中，且是根部门
                .filter(oaDept -> !rootCompanyId.equals(oaDept.getSubcompanyid1()) || (OAConstant.ROOT_COMPANY_ID.equals(oaDept.getSupdepid()) && rootCompanyDeptNames.contains(oaDept.getDepartmentname())))
                .map(dept -> deptConvert.dept2dept(dept, companyDeptMap))
                .toList();
        if (CollectionUtil.isEmpty(allParam)) {
            return Collections.emptyList();
        }
        Set<String> deptCodes = allParam.stream()
                .map(Dept::getDeptCode)
                .collect(Collectors.toSet());
        // 查询数据库的部门，转换成map
        Map<String, Long> deptMap = deptService.list(Wrappers.<Dept>lambdaQuery()
                        .eq(Dept::getDeptCategory, DeptCategory.DEPT.getCode())
                        .in(Dept::getDeptCode, deptCodes)
                ).stream()
                .filter(dept -> StringUtils.isNotEmpty(dept.getDeptCode()))
                .collect(Collectors.toMap(Dept::getDeptCode, Dept::getId, (a, b) -> b));
        // 处理部门
        return this.handleDept(allParam, deptMap, DeptCategory.DEPT);
    }

    /**
     *  处理部门
     * @param allParam 待处理的部门
     * @param deptMap   数据库所有部门编码和id map
     * @return 未处理的数据
     */
    private List<Dept> handleDept(List<Dept> allParam, Map<String, Long> deptMap, DeptCategory deptCategory) {
        // 数据库存在的所有部门id
        Set<Long> existsDeptIds = new HashSet<>(deptMap.values());
        allParam.forEach(dept -> {
            if (deptMap.containsKey(dept.getDeptCode())) {
                // 根据部门编码获取对应的部门id
                dept.setId(deptMap.get(dept.getDeptCode()));
            } else {
                // 没有就生成一个id
                dept.setId(DefaultIdentifierGenerator.getInstance().nextId(null));
                deptMap.put(dept.getDeptCode(), dept.getId());
            }
        });

        // 重新把没有父id的数据设置一下父id
        allParam.stream()
                .filter(dept -> dept.getParentId() == null && deptMap.containsKey(dept.getDeptCode()))
                .forEach(dept -> dept.setParentId(deptMap.get(dept.getParentCode())));

        // 父id不为空，保存数据
        List<Dept> list = allParam.stream()
                .filter(dept -> dept.getParentId() != null)
                .toList();
        // 不存在的新增
        List<Dept> addList = list.stream()
                .filter(dept -> !existsDeptIds.contains(dept.getId()))
                .toList();
        if (CollectionUtil.isNotEmpty(addList)) {
            ComposeLogUtil.getLastLog().info("批量新增{}：{}", deptCategory.getName(), addList.size());
            deptService.saveBatch(addList);
        }
        // 存在的修改
        List<Dept> updateList = list.stream()
                .filter(dept -> existsDeptIds.contains(dept.getId()))
                .toList();
        if (CollectionUtil.isNotEmpty(updateList)) {
            ComposeLogUtil.getLastLog().info("批量修改{}：{}", deptCategory.getName(), updateList.size());
            deptService.updateBatchById(updateList);
        }
        // 返回未处理的
        return allParam.stream()
                .filter(dept -> dept.getParentId() == null)
                .toList();
    }

    /**
     *  获取oa查询参数，子公司id参数
     * @return
     */
    private String getSubCompanyIds() {
        Set<String> companyNames = this.getCompanyNames();
        if (companyNames.isEmpty()) {
            return null;
        }
        return deptService.list(Wrappers.<Dept>lambdaQuery()
                        // 根据名称查询公司
                        .in(Dept::getDeptName, companyNames)
                        .eq(Dept::getDeptCategory, DeptCategory.COMPANY.getCode())
                ).stream()
                // 只要部门编码不为空，且包含了oa公司前缀的
                .filter(dept -> StringUtils.isNotBlank(dept.getDeptCode()) && dept.getDeptCode().contains(OAConvertConstant.COMPANY_OA_PREFIX))
                // 去掉oa公司前缀
                .map(dept -> dept.getDeptCode().replace(OAConvertConstant.COMPANY_OA_PREFIX, ""))
                .collect(Collectors.joining(","));
    }

    /**
     *  获取默认角色id
     */
    private String getDefaultRoleId() {
        // 从参数管理查询，没有取默认值，作为角色别名，查询角色
        String defaultRole = ParamCache.getValue(DEFAULT_PARAM_ROLE);
        if (defaultRole == null) {
            defaultRole = DEFAULT_ROLE;
        }
        List<Role> roleList = roleService.list(Wrappers.<Role>lambdaQuery()
                .eq(Role::getRoleAlias, defaultRole)
        );
        if (CollectionUtil.isEmpty(roleList)) {
            return null;
        }
        return roleList.get(0).getId().toString();
    }

    /**
     *  获取所有公司的编码和id的map
     * @return
     */
    private Map<String, Long> getAllCompanyDeptMap() {
        return deptService.list(Wrappers.<Dept>lambdaQuery()
                        .eq(Dept::getDeptCategory, DeptCategory.COMPANY.getCode())
                ).stream()
                .filter(dept -> StringUtils.isNotEmpty(dept.getDeptCode()))
                .collect(Collectors.toMap(Dept::getDeptCode, Dept::getId, (a, b) -> b));
    }

    /**
     *  获取需要的公司id
     * @return
     */
    private Set<String> getCompanyNames() {
        List<Dict> list = DictCache.getList(DictTypeEnum.SYNC_COMPANY_NAME.getType());
        if (CollectionUtil.isEmpty(list)) {
            ComposeLogUtil.getLastLog().warn("未查询到要同步的公司名称");
            return Collections.emptySet();
        }
        return list.stream()
                .filter(Objects::nonNull)
                .map(Dict::getDictValue)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());
    }

    /**
     *  获取根公司下需要同步的部门名称
     * @return
     */
    private Set<String> getRootCompanyDeptNames() {
        List<Dict> list = DictCache.getList(DictTypeEnum.SYNC_ROOT_COMPANY_DEPT_NAME.getType());
        if (CollectionUtil.isEmpty(list)) {
            ComposeLogUtil.getLastLog().warn("未查询到要同步的根公司下的部门名称");
            return Collections.emptySet();
        }
        return list.stream()
                .filter(Objects::nonNull)
                .map(Dict::getDictValue)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toSet());
    }

    /**
     *  获取根公司下需要同步的部门id
     * @param rootCompanyId
     * @return
     */
    private Set<String> getRootCompanyDeptIds(String rootCompanyId) {
        Set<String> rootCompanyDeptNames = this.getRootCompanyDeptNames();
        if (CollectionUtil.isEmpty(rootCompanyDeptNames)) {
            return Collections.emptySet();
        }
        // 查询父部门编码是根公司的，部门类型的，根公司下部门名称的部门
        return deptService.list(Wrappers.<Dept>lambdaQuery()
                        .in(Dept::getDeptName, rootCompanyDeptNames)
                        .eq(Dept::getDeptCategory, DeptCategory.DEPT.getCode())
                        .eq(Dept::getParentCode, OAConvertConstant.COMPANY_OA_PREFIX + rootCompanyId)
                ).stream()
                .filter(dept -> StringUtils.isNotBlank(dept.getDeptCode()))
                .map(dept -> dept.getDeptCode().replace(OAConvertConstant.DEPARTMENT_OA_PREFIX, ""))
                .collect(Collectors.toSet());
    }

    /**
     *  根公司id
     * @return
     */
    private String getRootCompanyId() {
        String companyName = DictCache.getValue(DictTypeEnum.SYNC_COMPANY_NAME.getType(), DICT_KEY_SYNC_ROOT_COMPANY_NAME);
        if (StringUtils.isBlank(companyName)) {
            ComposeLogUtil.getLastLog().warn("未查询到配置的根公司名称");
            return null;
        }
        Dept dept = deptService.getOne(Wrappers.<Dept>lambdaQuery()
                .eq(Dept::getDeptName, companyName)
                .eq(Dept::getDeptCategory, DeptCategory.COMPANY.getCode())
                .last("limit 1")
        );
        if (dept == null) {
            ComposeLogUtil.getLastLog().warn("未查询到根公司 名称：{}", companyName);
            return null;
        }
        if (StringUtils.isBlank(dept.getDeptCode())) {
            ComposeLogUtil.getLastLog().warn("根公司编码为空：{}", companyName);
            return null;
        }
        // 部门编码去掉前缀，就是oa的id
        return dept.getDeptCode().replace(OAConvertConstant.COMPANY_OA_PREFIX, "");
    }

    /**
     *  获取用户部门唯一标识，用户id+公司编码+部门编码
     * @param userDept
     * @return
     */
    private String getUserDeptKey(UserDept userDept) {
        if (userDept == null) {
            return null;
        }
        return userDept.getUserId() + userDept.getCompanyCode() + userDept.getDeptCode();
    }
}
