package jnpf.personnels.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jnpf.base.UserInfo;
import jnpf.base.entity.SuperBaseEntity;
import jnpf.database.util.TenantDataSourceUtil;
import jnpf.exception.LoginException;
import jnpf.model.enums.FtbPersonnelsAuditTaskEnum;
import jnpf.model.enums.FtbPersonnelsCofigEnum;
import jnpf.model.personnels.dto.audit.FtbPersonnelsAuditDto;
import jnpf.model.personnels.dto.config.FtbPersionnelsSendCranbonCopy;
import jnpf.model.personnels.po.*;
import jnpf.model.personnels.vo.config.FtbPersonnelsAuditRunTaskInfo;
import jnpf.model.personnels.vo.task.FtbPersonnelsAuditRunTaskVO;
import jnpf.personnels.mapper.FtbPersonnelsAuditRunTaskMapper;
import jnpf.personnels.mapper.FtbPersonnelsAuditSubConfigMapper;
import jnpf.personnels.mapper.FtbPersonnelsSecondmentManagementMapper;
import jnpf.personnels.mapper.FtbPersonnelsTransferManageMapper;
import jnpf.personnels.service.*;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
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;

@Service
@Slf4j
public class  FtbPersonnelsAuditRunTaskServiceImpl extends ServiceImpl<FtbPersonnelsAuditRunTaskMapper, FtbPersonnelsAuditRunTask> implements FtbPersonnelsAuditRunTaskService {

    @Resource
    FtbPersonnelsAuditTaskInfoService taskInfoService;


    @Resource
    FtbPersonnelsAuditRunTaskHistoryService runTaskHistoryService;

    @Resource
    FtbPersonnelsAuditMasterConfigService configService;

    @Resource
    FtbPersonnelsAuditSubConfigMapper subConfigMapper;

    @Resource
    FtbPersonnelsAuditCarbonRecipientService carbonRecipientService;

    @Resource
    FtbPersonnelsRegularManagementService regularManagementService;

    @Resource
    FtbPersonnelsStaffTransferPositionService transferPositionService;

    @Resource
    FtbPersonnelsTurnoverManagementService turnoverManagementService;

    @Resource
    FtbPersonnelsPostApplyService personnelsPostApplyService;

    @Autowired
    FtbPersonnelsStaffRosterService staffRosterService;

    @Autowired
    private FtbPersonnelsTransferManageMapper ftbPersonnelsTransferManageMapper;

    @Resource
    FtbPersonnelsSecondmentManagementMapper ftbPersonnelsSecondmentManagementMapper;


    @Override
    @Transactional(rollbackFor = {Exception.class,RuntimeException.class})
    public String startTheReviewProcess(String businessId, Integer type, String orgId, String userId) {
        // 校验是否存在对应的审核流程配置
        FtbPersonnelsAuditMasterConfig config = configService.lambdaQuery()
                .eq(FtbPersonnelsAuditMasterConfig::getOrgId, orgId)
                .eq(FtbPersonnelsAuditMasterConfig::getConfigType, type)
                .eq(FtbPersonnelsAuditMasterConfig::getEnableMark,"0").one();
        if (ObjectUtil.isEmpty(config)){
            throw new RuntimeException("您所选的组织没有配置相关审批流程，请在“人事审批权限配置”中进行配置后再提交审批！");
        }
        LambdaQueryWrapper<FtbPersonnelsAuditSubConfig> lambdaed = Wrappers.lambdaQuery();
        lambdaed.eq(FtbPersonnelsAuditSubConfig::getMasterId, config.getId());
        List<FtbPersonnelsAuditSubConfig> auditSubConfigs = subConfigMapper.selectList(lambdaed);
        List<String> stringList = auditSubConfigs.stream().map(FtbPersonnelsAuditSubConfig::getAuditorId).collect(Collectors.toList());
        if (stringList.contains(userId)){
            throw new RuntimeException("您是对应组织审批人,无法对应发起流程,请替换审批人后重试!");
        }
        String theReviewProcess = checkWhetherTheCurrentPersonnelIsInTheReviewProcess(userId);
        if (StringUtil.isNotEmpty(theReviewProcess)){
            // 1 转正 2 调岗, 3 离职
            String str="";
            switch (theReviewProcess){
                case "1":
                    str = "转正";
                    break;
                case "2":
                    str = "调岗";
                    break;
                case "3":
                    str = "离职";
                    break;
                case "4":
                    str = "晋升";
                    break;
            }
            throw new RuntimeException("当前人员处于"+str+"审批中,请勿重复进行审批!");
        }
        // 1.根据业务主键查询是否存在审核记录
        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTask::getBusinessId, businessId);
        FtbPersonnelsAuditRunTask auditRunTask =  baseMapper.selectOne(wrapper);
        if (ObjectUtil.isNotEmpty(auditRunTask)){
            // throw new RuntimeException("该业务已经存在审核记录，请勿重复提交审核");
            FtbPersonnelsAuditRunTaskHistory runTaskHistory =new FtbPersonnelsAuditRunTaskHistory();
            BeanUtil.copyProperties(auditRunTask, runTaskHistory);
            runTaskHistory.setId(auditRunTask.getId());
            runTaskHistoryService.save(runTaskHistory);
            baseMapper.deleteById(auditRunTask.getId());
        }
        // 2.如果不存在审核记录，新建一条审核流程开启审核
        FtbPersonnelsAuditRunTask runTask = new FtbPersonnelsAuditRunTask();
        runTask.setBusinessId(businessId);
        runTask.setMasterAuditConfigId(config.getId());
        // 查询是否是会签
        if ( ObjectUtil.isEmpty(config.getIsOnePersonPasses()) ||  config.getIsOnePersonPasses() != 1) {
            // 会签初始化执行人节点id
            List<FtbPersonnelsAuditSubConfig> subConfig = subConfigMapper.queryInitializeExecutionNode(orgId, type, config.getIsOnePersonPasses());
            runTask.setUserId(subConfig.get(0).getAuditorId());
        }
        runTask.setExcuseStatus(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode());
        baseMapper.insert(runTask);
        return runTask.getId();
    }

    @Override
    public Boolean checkWhetherTheCurrentSignIsOr(String businessId, Integer configType, String userId) {
        // 1.查询当前业务是否开启审核
        String s = baseMapper.queryHaveRuntask(businessId, configType,userId);
        if (ObjectUtil.isEmpty(s)){
            // 不存在审核记录，直接返回撤销审核结果
            return false;
        }
        FtbPersonnelsAuditMasterConfig masterConfig = getMasterConfig(s);
        // 一人审批通过即视为该流程全部审批通过(0否,1是)
        // 一人或签
        if (ObjectUtil.isEmpty(masterConfig)){
            return false;
        }
        if (masterConfig.getIsOnePersonPasses() != null && masterConfig.getIsOnePersonPasses() == 1){
            return true;
        }
        return false;
    }

    @Override
    public Boolean checkWhetherTheCurrentApproverIs(String userId) {
        LambdaQueryWrapper<FtbPersonnelsAuditSubConfig> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditSubConfig::getAuditorId,userId);
        List<FtbPersonnelsAuditSubConfig> personnelsAuditSubConfigs = subConfigMapper.selectList(wrapper);
        if (CollUtil.isNotEmpty(personnelsAuditSubConfigs)){
            return true;
        }
        return false;
    }

    @Override
    public Boolean checkIsTheCurrentBusinessInTheApprovalProcess(String businessId) {
        FtbPersonnelsAuditRunTask runTask = getFtbPersonnelsAuditRunTask(businessId);
        if (ObjectUtil.isEmpty(runTask)){
            return false;
        }
        return true;
    }

    @Override
    public FtbPersonnelsCofigEnum checksItInTheReviewProcess(String businessId) {
        FtbPersonnelsAuditRunTask runTask = getFtbPersonnelsAuditRunTask(businessId);
        if (ObjectUtil.isEmpty(runTask)){
            return null;
        }
        FtbPersonnelsAuditMasterConfig entity = configService.lambdaQuery().eq(SuperBaseEntity.SuperIBaseEntity::getId,
                runTask.getMasterAuditConfigId()).one();
        return  FtbPersonnelsCofigEnum.getConfigType(entity.getConfigType());
    }



    @Override
    @Transactional(rollbackFor = {Exception.class,RuntimeException.class})
    public  synchronized FtbPersonnelsAuditTaskEnum performReview(FtbPersonnelsAuditDto auditDto,String... userIds) {
        // 1.查询当前业务是否开启审核
        String userId =  CollUtil.isNotEmpty(List.of(userIds)) ? userIds[0] : UserProvider.getUser().getUserId();
        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTask::getBusinessId, auditDto.getBusinessId());
        FtbPersonnelsAuditRunTask runTask = baseMapper.selectOne(wrapper);
        if (ObjectUtil.isEmpty(runTask)){
            FtbPersonnelsAuditRunTaskHistory entity = runTaskHistoryService.lambdaQuery()
                    .eq(FtbPersonnelsAuditRunTaskHistory::getBusinessId, auditDto.getBusinessId())
                    .orderByDesc(SuperBaseEntity.SuperCBaseEntity::getCreatorTime).last("limit 1").one();
            if (ObjectUtil.isNotEmpty(entity)){
                boolean equals = entity.getExcuseStatus().equals(FtbPersonnelsAuditTaskEnum.CANCEL.getCode());
                if (equals){
                    throw new RuntimeException("该业务申请已经撤销，请勿提交审核!");
                }
            }
            // 不存在审核记录，直接返回撤销审核结果
            throw new RuntimeException("不存在对应的审核流程! ");
        }
        FtbPersonnelsAuditMasterConfig masterConfig = getMasterConfig(runTask.getMasterAuditConfigId());
        // 校验是否审核意见为必填
        if (masterConfig.getIsApprovalComments() != null &&  masterConfig.getIsApprovalComments() == 1 ){
            if (ObjectUtil.isEmpty(auditDto.getApprovalComments())){
                throw new RuntimeException("审核意见为必填项");
            }
        }
        List<FtbPersonnelsAuditSubConfig> subConfig = subConfigMapper.queryInitializeExecutionNode
                (masterConfig.getOrgId(), masterConfig.getConfigType(), null);
        // 一人审批通过即视为该流程全部审批通过(0否,1是)
        // 3.查询是离职才会有 或签 执行人节点
        // UserInfo userInfo = UserProvider.getUser();
        // 一人或签
        FtbPersonnelsAuditTaskEnum result;
        if (masterConfig.getIsOnePersonPasses() != null &&  masterConfig.getIsOnePersonPasses() == 1){
            List<FtbPersonnelsAuditTaskInfo> taskInfoList = getAuditTaskInfos(auditDto, subConfig, userId, runTask,null);
            if ("0".equals(auditDto.getFlag())){ //不通过
                result = FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED;
            }else {
                result = FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED;
            }
            taskInfoService.saveBatch(taskInfoList);
            // 一人或签更改流程最终状态
            runTask.setExcuseStatus(result.getCode());
            baseMapper.updateById(runTask);
            return result;
        }
        // 会签 2.获取当前审核人是否为配置审核人是否相同
        if (!userId.equals(runTask.getUserId())){
            throw new RuntimeException("当前任务审核人与登录人不一致,无法提交审核!");
        }
        // 4.获取当前人审核配置是否具有对应的权限
        FtbPersonnelsAuditSubConfig auditSubConfig = subConfig.stream()
                .filter(item -> item.getAuditorId().equals(userId)).findFirst().orElse(null);
        if (ObjectUtils.isEmpty(auditSubConfig)){
            throw new RuntimeException("当前登录人没有该审核人的权限,无法提交审核!");
        }
        FtbPersonnelsAuditTaskInfo taskInfo = new FtbPersonnelsAuditTaskInfo();
        if(StringUtils.isEmpty(auditSubConfig.getBlacklistFilling())
                && "0".equals(auditSubConfig.getBlacklistFilling())
                && auditDto.getIsBeBlackList() != null){
            throw new RuntimeException("当前登录人没有填写黑名单的权限,无法提交审核!");
        }else {
            taskInfo.setIsBeBlackList(auditDto.getIsBeBlackList());
            // 加入黑名单
            taskInfo.setBlacklistCause(auditDto.getBlacklistCause());
            taskInfo.setBlackListPeriod(auditDto.getBlackListPeriod());
            taskInfo.setBlackTypeId(auditDto.getBlackTypeId());
        }
        if ("0".equals(auditSubConfig.getPayrollEntry()) && ObjectUtil.isNotEmpty(auditDto.getSalary())) {
            throw new RuntimeException("当前登录人没有薪资填写权限,无法填写薪资!");
        }else {
            taskInfo.setPayrollEntry(auditDto.getSalary());
        }
        if ("0".equals(auditSubConfig.getPayrollAudit()) && ObjectUtil.isNotEmpty(auditDto.getDoesTheSalaryComplyWith())){
            throw new RuntimeException("当前登录人没有薪资审核权限,无法审核薪资!");
        }else {
            taskInfo.setPayrollAudit(auditDto.getDoesTheSalaryComplyWith());
        }
        // 5.执行审核 返回最终流程审核状态
        // 5.1根据对应的审核状态执行流程
        taskInfo.setRunTaskId(runTask.getId());
        taskInfo.setUserId(userId);
        taskInfo.setApprovalOpinion(auditDto.getApprovalComments());
        if ("1".equals(auditDto.getFlag())){
            taskInfo.setApprovalResult("1");
        } else if ("0".equals(auditDto.getFlag())){
            taskInfo.setApprovalResult("0");
        }
        taskInfoService.save(taskInfo);
        String nextReview = auditSubConfig.getNextReview();
        // 创建返回值赋值
        FtbPersonnelsAuditTaskEnum returnCode = null;
        // 创建历史记录表
        if ("0".equals(nextReview) && "1".equals(auditDto.getFlag())){
            // 将下一个节点置为 null 返回
            runTask.setUserId("0");
            Integer code = FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED.getCode();
            returnCode = FtbPersonnelsAuditTaskEnum.EXAMINATION_PASSED;
            runTask.setExcuseStatus(code);
        }else{
            // 5.2如果为通过且下一节点不为空 需要将执行人id 进行替换
            if ("1".equals(auditDto.getFlag())){
                String auditorId = Objects.requireNonNull(subConfig.stream().filter(item -> nextReview.equals(item.getId())).findFirst().orElse(null)).getAuditorId();
                runTask.setUserId(auditorId);
                Integer underReviewCode = FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode();
                runTask.setExcuseStatus(underReviewCode);
                returnCode = FtbPersonnelsAuditTaskEnum.UNDER_REVIEW;
            } else if ("0".equals(auditDto.getFlag())){
                // 5.3如果为不通过则流程结束将审核结果置为不通过,记录到历史审核记录中
                runTask.setUserId("0");
                Integer auditNotPassedCode = FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED.getCode();
                runTask.setExcuseStatus(auditNotPassedCode);
                returnCode = FtbPersonnelsAuditTaskEnum.AUDIT_NOT_PASSED;
                initializationDoesNotPassData(subConfig, userId, runTask);
            }
        }
        baseMapper.updateById(runTask);
        return returnCode;
    }

    /**
     * 初始化不通过数据
     * @param subConfig
     * @param runTask
     */
    private void initializationDoesNotPassData(List<FtbPersonnelsAuditSubConfig> subConfig, String userId, FtbPersonnelsAuditRunTask runTask) {
        int k =0;
        for (int i = 0; i < subConfig.size(); i++) {
            FtbPersonnelsAuditSubConfig item = subConfig.get(i);
            if (item.getAuditorId().equals(userId) && !item.getNextReview().equals("0")){
                k = i;
            }else if (item.getAuditorId().equals(userId) && item.getNextReview().equals("0")){
                return;
            }
        }
        if (k+1 != subConfig.size()) {
            List<FtbPersonnelsAuditSubConfig> subConfigList = subConfig.subList(k+1, subConfig.size());
            if (CollUtil.isNotEmpty(subConfigList)) {
                List<FtbPersonnelsAuditTaskInfo> taskInfoList = initNotPassedInfos(subConfigList, runTask.getId());
                // 不通过直接将数据初始化
                taskInfoService.saveBatch(taskInfoList);
            }
        }
    }

    @NotNull
    private static List<FtbPersonnelsAuditTaskInfo> initNotPassedInfos(List<FtbPersonnelsAuditSubConfig> subConfig,
                                                                       String runTaskId) {
        List<FtbPersonnelsAuditTaskInfo> taskInfoList = subConfig.stream().map(item -> {
            FtbPersonnelsAuditTaskInfo info = new FtbPersonnelsAuditTaskInfo();
            info.setRunTaskId(runTaskId);
            // 审核是否通过(0不通过,1通过,2不通过(自动))
            info.setUserId(item.getAuditorId());
            info.setUserName(item.getAuditorName());
            info.setApprovalResult("2");
            return info;
        }).collect(Collectors.toList());
        return taskInfoList;
    }

    @NotNull
    private static List<FtbPersonnelsAuditTaskInfo> getAuditTaskInfos(FtbPersonnelsAuditDto auditDto,
                                                                      List<FtbPersonnelsAuditSubConfig> subConfig,
                                                                      String userId,
                                                                      FtbPersonnelsAuditRunTask runTask,String id) {
        List<String> UserIds = subConfig.stream().map(FtbPersonnelsAuditSubConfig::getAuditorId).collect(Collectors.toList());
        if (!UserIds.contains(userId)){
            throw new RuntimeException("当前配置审核人列表中不存在当前登录人,无法提交审核!");
        }

        List<FtbPersonnelsAuditTaskInfo> taskInfoList = subConfig.stream().map(item -> {
            FtbPersonnelsAuditTaskInfo info = new FtbPersonnelsAuditTaskInfo();
            info.setRunTaskId(runTask.getId());
            // 为当前审批人
            if (userId.equals(item.getAuditorId())) {
                if(ObjectUtil.isEmpty(item.getBlacklistFilling()) && "0".equals(item.getBlacklistFilling()) && auditDto.getIsBeBlackList() != null){
                    throw new RuntimeException("当前登录人没有填写黑名单的权限,无法提交审核!");
                }else {
                    info.setIsBeBlackList(auditDto.getIsBeBlackList());
                    // 加入黑名单
                    info.setBlacklistCause(auditDto.getBlacklistCause());
                    info.setBlackListPeriod(auditDto.getBlackListPeriod());
                    info.setBlackTypeId(auditDto.getBlackTypeId());
                }
                info.setUserId(userId);
                info.setApprovalOpinion(auditDto.getApprovalComments());
                info.setApprovalResult(auditDto.getFlag());
                if (StringUtils.isNotEmpty(id)) {
                    info.setId(id);
                }
            } else {
                // 审核是否通过(0不通过,1通过,2不通过(自动),3通过(自动))
                info.setUserId(item.getAuditorId());
                info.setUserName(item.getAuditorName());
                if ("0".equals(auditDto.getFlag())) {
                    info.setApprovalResult("2");
                } else if ("1".equals(auditDto.getFlag())) {
                    info.setApprovalResult("3");
                }
            }
            return info;
        }).collect(Collectors.toList());
        return taskInfoList;
    }

    @Override
    @Transactional(rollbackFor = {Exception.class,RuntimeException.class})
    public FtbPersonnelsAuditTaskEnum withdrawTheReviewProcess(String businessId) {
        FtbPersonnelsAuditRunTask auditRunTask = getFtbPersonnelsAuditRunTask(businessId);
        if (ObjectUtil.isEmpty(auditRunTask)){
            // 不存在审核记录，直接返回撤销审核结果
            throw new RuntimeException("该申请已撤销!");
        }
        // 撤销对应的审核流程将审核流程最终结果置为撤销
        auditRunTask.setExcuseStatus(FtbPersonnelsAuditTaskEnum.CANCEL.getCode());
        // 初始化剩下的审核流程节点 查询sql已处理
        // 将流程同步到历史流程中
        FtbPersonnelsAuditRunTaskHistory runTaskHistory = new FtbPersonnelsAuditRunTaskHistory();
        auditRunTask.setUserId("0");
        BeanUtil.copyProperties(auditRunTask, runTaskHistory);
        runTaskHistory.setId(auditRunTask.getId());
        boolean save = runTaskHistoryService.save(runTaskHistory);
        if (!save){
            throw new RuntimeException("撤销审核失败");
        }
        // 将run task中的数据进行删除
        baseMapper.deleteById(auditRunTask.getId());
        return FtbPersonnelsAuditTaskEnum.NOT_PROCESSED;
    }


    @Override
    public FtbPersonnelsAuditTaskEnum getWhetherLoginPerToTheAuditNode(String businessId,
                                                                       FtbPersonnelsCofigEnum ftbPersonnelsCofigEnum) {
        UserInfo user = UserProvider.getUser();
        // 获取主配置是或签 还是 会签
        String masterAuditConfigId = baseMapper.queryHaveRuntask(businessId, ftbPersonnelsCofigEnum.getConfigType(), user.getUserId());
        if (ObjectUtil.isEmpty(masterAuditConfigId)) return null;
        FtbPersonnelsAuditMasterConfig entity = getMasterConfig(masterAuditConfigId);
        // 或签 一人通过即为全部通过
        if ( entity.getIsOnePersonPasses() != null && entity.getIsOnePersonPasses() == 1){
            return FtbPersonnelsAuditTaskEnum.PENDING;
        }
        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTask::getBusinessId,businessId);
        wrapper.eq(FtbPersonnelsAuditRunTask::getUserId,user.getUserId());
        FtbPersonnelsAuditRunTask auditRunTask = baseMapper.selectOne(wrapper);
        log.info("当前审核任务:{}",auditRunTask);
        if (ObjectUtil.isEmpty(auditRunTask)){
            // 还未到当前人审核节点
            return FtbPersonnelsAuditTaskEnum.UNDER_REVIEW;
        }

        // 将当前审核节点为待审核节点
        return FtbPersonnelsAuditTaskEnum.PENDING;
    }


    @Override
    public FtbPersonnelsAuditRunTaskVO viewTheCurrentApprovalProcessByTaskId(String id) {
        FtbPersonnelsAuditRunTaskVO runTaskVO;
        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTask::getId,id);
        wrapper.last("limit 1");
        FtbPersonnelsAuditRunTask auditRunTask = baseMapper.selectOne(wrapper);
        String masterAuditConfigId = "";
        if(ObjectUtil.isEmpty(auditRunTask)){
            FtbPersonnelsAuditRunTaskHistory one = runTaskHistoryService.lambdaQuery()
                    .eq(SuperBaseEntity.SuperIBaseEntity::getId, id).one();
            if (ObjectUtil.isEmpty(one)){
                return new FtbPersonnelsAuditRunTaskVO();
            }
            FtbPersonnelsAuditRunTask target = new FtbPersonnelsAuditRunTask();
            BeanUtil.copyProperties(one, target);
            runTaskVO = FtbPersonnelsAuditRunTaskVO.coverFtbPersonnelsAuditRunTaskVO(target);
            List<FtbPersonnelsAuditRunTaskInfo> list = taskInfoService.getHisTaskInfos(one.getId(),
                    one.getMasterAuditConfigId());
            masterAuditConfigId = target.getMasterAuditConfigId();
            runTaskVO.setTaskInfos(list);
        }else {
            runTaskVO = FtbPersonnelsAuditRunTaskVO.coverFtbPersonnelsAuditRunTaskVO(auditRunTask);
            List<FtbPersonnelsAuditRunTaskInfo> list = taskInfoService.getRunTaskInfos(auditRunTask.getBusinessId(),
                    auditRunTask.getMasterAuditConfigId());
            masterAuditConfigId = auditRunTask.getMasterAuditConfigId();
            List<FtbPersonnelsAuditRunTaskHistory> taskHistories = runTaskHistoryService.lambdaQuery()
                    .eq(FtbPersonnelsAuditRunTaskHistory::getBusinessId, auditRunTask.getBusinessId())
                    .list();
            if (CollUtil.isNotEmpty(taskHistories)){
                runTaskVO.setMarkForReApproval("1");
            }
            runTaskVO.setTaskInfos(list);
        }
        setApprovalProperties(runTaskVO,masterAuditConfigId);
        return runTaskVO;
    }

    @Override
    public String checkWhetherTheCurrentPersonnelIsInTheReviewProcess(String userId) {
        // null 不处于 ,1转正 2,调岗, 3离职
        //0,待审批,1审批中 FtbPersonnelsAuditTaskEnum
        List<Integer> list = new ArrayList<>();
        Integer codePENDING = FtbPersonnelsAuditTaskEnum.PENDING.getCode();
        Integer codeUNDERREVIEW = FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode();
        list.add(codePENDING);
        list.add(codeUNDERREVIEW);
        List<FtbPersonnelsRegularManagement> regularManagements = regularManagementService.lambdaQuery()
                .eq(FtbPersonnelsRegularManagement::getUserId, userId)
                .in(FtbPersonnelsRegularManagement::getTransferStatus, list)
                .eq(FtbPersonnelsRegularManagement::getEnableMark,0).list();
        Long aLong = getStringsForOA(regularManagements.stream().map(SuperBaseEntity.SuperIBaseEntity::getId));
        if (aLong > 0){
            log.debug("当前用户正在转正审核流程中");
            return "1";
        }
        List<FtbPersonnelsTurnoverManagement> turnoverManagements = turnoverManagementService.lambdaQuery()
                .eq(FtbPersonnelsTurnoverManagement::getUserId, userId)
                .in(FtbPersonnelsTurnoverManagement::getTurnoverStatus, list)
                .eq(FtbPersonnelsTurnoverManagement::getEnableMark,0).list();
        Long turnoverCount = getStringsForOA(turnoverManagements.stream().map(SuperBaseEntity.SuperIBaseEntity::getId));
        if (turnoverCount > 0){
            log.debug("当前用户正在离职审核流程中!");
            return "3";
        }
        // 调动模块
        LambdaQueryWrapper<FtbPersonnelsTransferManage> transferManages = Wrappers.lambdaQuery();
        transferManages.eq(FtbPersonnelsTransferManage::getUserId, userId);
        transferManages.in(FtbPersonnelsTransferManage::getProcessingStatus, list);
        transferManages.eq(FtbPersonnelsTransferManage::getEnableMarkd, 0);
        transferManages.last("limit 1");
        FtbPersonnelsTransferManage transferManage = ftbPersonnelsTransferManageMapper.selectOne(transferManages);
        if (Objects.nonNull(transferManage)) {
            // 调动类型0调岗1晋升2降职3调店 转换为2,调岗, 4晋升 5调店 6降职
            Integer transferType = transferManage.getState();
            switch (transferType) {
                case 0:
                    return "2";
                case 1:
                    return "4";
                case 2:
                    return "6";
                case 3:
                    return "5";
                default:
                    break;
            }
        }
        LambdaQueryWrapper<FtbPersonnelsSecondmentManagement> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(FtbPersonnelsSecondmentManagement::getUserId, userId);
        queryWrapper.in(FtbPersonnelsSecondmentManagement::getTransferStatus, List.of(codeUNDERREVIEW));
        queryWrapper.eq(FtbPersonnelsSecondmentManagement::getEnableMark,0);
        FtbPersonnelsSecondmentManagement ftbPersonnelsSecondmentManagement = ftbPersonnelsSecondmentManagementMapper.selectOne(queryWrapper);
        if (Objects.nonNull(ftbPersonnelsSecondmentManagement)){
           return "7";
        }
        return null;
    }

    @Override
    public void deleteReviewProcessAndRecords(String runTaskId, String businessId) {
        // 移除审批数据
        baseMapper.deleteById(runTaskId);
        // 移除历史审批数据
        LambdaQueryWrapper<FtbPersonnelsAuditRunTaskHistory> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTaskHistory::getBusinessId,businessId);
        List<FtbPersonnelsAuditRunTaskHistory> listed = runTaskHistoryService.list(wrapper);
        LambdaQueryWrapper<FtbPersonnelsAuditTaskInfo> infoWrapper = Wrappers.lambdaQuery();
        List<String> list = new ArrayList<>();
        list.add(runTaskId);
        List<String> stringList = listed.stream().map(SuperBaseEntity.SuperIBaseEntity::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(stringList)){
            list.addAll(stringList);
            runTaskHistoryService.removeBatchByIds(stringList);
        }
        infoWrapper.in(FtbPersonnelsAuditTaskInfo::getRunTaskId,list);
        taskInfoService.remove(infoWrapper);
    }

    @Override
    public void closeAllExecutionData(List<String> teantIdList) {
        for (String tenantId : teantIdList) {
            try {
                TenantDataSourceUtil.switchTenant(tenantId);
            } catch (LoginException e) {
                throw new RuntimeException(e);
            }
            // 多个租户执行
            LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
            wrapper.in(FtbPersonnelsAuditRunTask::getExcuseStatus, 0,1);
            List<FtbPersonnelsAuditRunTask> runTaskList = baseMapper.selectList(wrapper);

            // 一人审批单独处理
            List<FtbPersonnelsAuditRunTask> onePersonApprovesList = runTaskList.stream().filter(item -> StringUtil.isEmpty(item.getUserId())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(onePersonApprovesList)) onePersonApproves(onePersonApprovesList);
            // 流程审批
            List<FtbPersonnelsAuditRunTask> processApprovalRejectionList = runTaskList.stream().filter(item -> StringUtil.isNotEmpty(item.getUserId())).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(processApprovalRejectionList)) processApprovalRejection(processApprovalRejectionList);
        }
    }

    /**
     * 流程处理
     * @param processApprovalRejectionList
     */
    private void  processApprovalRejection(List<FtbPersonnelsAuditRunTask> processApprovalRejectionList){
        FtbPersonnelsAuditDto auditDto = new FtbPersonnelsAuditDto();
        auditDto.setFlag("0");
        for (FtbPersonnelsAuditRunTask runTask : processApprovalRejectionList) {
            auditDto.setBusinessId(runTask.getBusinessId());
            auditDto.setApprovalComments("审批不通过");
            auditDto.setBusinessId(runTask.getBusinessId());
            try {
                performReview(auditDto,runTask.getUserId());
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 一人审批处理
     * @param onePersonApprovesList
     */
    public void  onePersonApproves(List<FtbPersonnelsAuditRunTask> onePersonApprovesList) {
        // 反向查询对应需要的userId
        FtbPersonnelsAuditDto auditDto = new FtbPersonnelsAuditDto();
        auditDto.setFlag("0");
        for (FtbPersonnelsAuditRunTask runTask : onePersonApprovesList) {
            String masterAuditConfigId = runTask.getMasterAuditConfigId();
            LambdaQueryWrapper<FtbPersonnelsAuditSubConfig> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(FtbPersonnelsAuditSubConfig::getMasterId,masterAuditConfigId);
            List<FtbPersonnelsAuditSubConfig> auditSubConfigs = subConfigMapper.selectList(wrapper);
            auditDto.setBusinessId(runTask.getBusinessId());
            auditDto.setApprovalComments("审批不通过");
            if (CollUtil.isNotEmpty(auditSubConfigs)){
                String auditorId = auditSubConfigs.get(0).getAuditorId();
                try {
                    performReview(auditDto, auditorId);
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }

    }

    @NotNull
    private Long getStrings(Stream<String> stream,List<Integer> list) {
        List<String> idsTransfer = stream.collect(Collectors.toList());
        if (CollUtil.isEmpty(idsTransfer)){
            return 0L;
        }
        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> transferQueryWrapper = Wrappers.lambdaQuery();
        transferQueryWrapper.in(FtbPersonnelsAuditRunTask::getBusinessId,idsTransfer);
        transferQueryWrapper.in(FtbPersonnelsAuditRunTask::getExcuseStatus, list);
        return  baseMapper.selectCount(transferQueryWrapper);
    }
    @NotNull
    private Long getStringsForOA(Stream<String> stream) {
        List<String> idsTransfer = stream.collect(Collectors.toList());
        if (CollUtil.isEmpty(idsTransfer)){
            return 0L;
        }
        // OA 不走数自定义表校验
        return (long) idsTransfer.size();
    }

    @Override
    public FtbPersonnelsAuditRunTaskVO viewTheCurrentApprovalProcess(String id) {

        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTask::getBusinessId,id);
        wrapper.last("limit 1");
        FtbPersonnelsAuditRunTask auditRunTask = baseMapper.selectOne(wrapper);
        if(ObjectUtil.isEmpty(auditRunTask)){
            throw new RuntimeException("当前任务未开启审批!");
        }
        FtbPersonnelsAuditRunTaskVO runTaskVO = FtbPersonnelsAuditRunTaskVO.coverFtbPersonnelsAuditRunTaskVO(auditRunTask);
        List<FtbPersonnelsAuditRunTaskInfo> list = taskInfoService.getRunTaskInfos(id, auditRunTask.getMasterAuditConfigId());
        runTaskVO.setTaskInfos(list);
        setApprovalProperties( runTaskVO, auditRunTask.getMasterAuditConfigId());
        return runTaskVO;
    }

    private void setApprovalProperties(FtbPersonnelsAuditRunTaskVO runTaskVO, String str) {
        List<FtbPersonnelsAuditCarbonRecipient> carbonRecipientList = carbonRecipientService.lambdaQuery()
                .eq(FtbPersonnelsAuditCarbonRecipient::getMasterConfig, str).list();
        List<FtbPersionnelsSendCranbonCopy> sendCranbonCopies = carbonRecipientList.stream().map(FtbPersonnelsAuditCarbonRecipient::coverFtbPersionnelsSendCranbonCopy).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(sendCranbonCopies)) {
            LambdaQueryWrapper<FtbPersonnelsStaffRoster> lambdaQuery = Wrappers.lambdaQuery();
            lambdaQuery.in(FtbPersonnelsStaffRoster::getUserId,sendCranbonCopies.stream()
                    .map(FtbPersionnelsSendCranbonCopy::getCcId).distinct()
                    .collect(Collectors.toList()));
            List<FtbPersonnelsStaffRoster> staffRosters = staffRosterService.list(lambdaQuery);
            Map<String, String> map = staffRosters.stream().collect(Collectors.toMap(FtbPersonnelsStaffRoster::getUserId, FtbPersonnelsStaffRoster::getName,(a, b)->a));
            sendCranbonCopies.forEach(item->{
                if (map.containsKey(item.getCcId())) item.setCcName(map.get(item.getCcId()));
            });
            runTaskVO.setCopyRecipient(sendCranbonCopies);
        }
    }

    @Override
    public List<String> queryInfoThatCurrentUserNeedsToApprove(String userId, FtbPersonnelsCofigEnum ftbPersonnelsCofigEnum) {

        return baseMapper.queryInfoThatCurrentUserNeedsToApprove(userId,ftbPersonnelsCofigEnum.getConfigType());
    }

    @Override
    public List<String> queryMyApprovedReviewProcess(String userId, FtbPersonnelsCofigEnum ftbPersonnelsCofigEnum) {
        return baseMapper.queryMyApprovedReviewProcess(userId,ftbPersonnelsCofigEnum.getConfigType());
    }



    /**
     * 获取对应的主配置数据
     * @param mstRunTaskId 主配置id
     * @return 主配置信息
     */
    private FtbPersonnelsAuditMasterConfig getMasterConfig(String mstRunTaskId) {
        return configService.lambdaQuery()
                .eq(SuperBaseEntity.SuperIBaseEntity::getId,mstRunTaskId).one();
    }
    /**
     * 是否开启审核流程
     * @param businessId 业务主键
     * @return FtbPersonnelsAuditRunTask 当前执行任务
     */
    private FtbPersonnelsAuditRunTask getFtbPersonnelsAuditRunTask(String businessId) {
        LambdaQueryWrapper<FtbPersonnelsAuditRunTask> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(FtbPersonnelsAuditRunTask::getBusinessId, businessId);
        List<Integer> list = new ArrayList<>();
        list.add(FtbPersonnelsAuditTaskEnum.PENDING.getCode());
        list.add(FtbPersonnelsAuditTaskEnum.UNDER_REVIEW.getCode());
        wrapper.in(FtbPersonnelsAuditRunTask::getExcuseStatus,list);
        return baseMapper.selectOne(wrapper);
    }

}
