package com.yifu.cloud.plus.v1.yifu.salary.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.yifu.cloud.plus.v1.yifu.admin.api.entity.SysUser;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.SysUserListVo;
import com.yifu.cloud.plus.v1.yifu.admin.api.vo.UserApprovalRoleVO;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.exception.CheckedException;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.ProcessDaprUtils;
import com.yifu.cloud.plus.v1.yifu.common.dapr.util.UpmsDaprUtils;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TAuditNodeProcess;
import com.yifu.cloud.plus.v1.yifu.salary.entity.TAuditRecord;
import com.yifu.cloud.plus.v1.yifu.salary.service.TAuditRecordService;
import com.yifu.cloud.plus.v1.yifu.salary.service.TAuditNodeProcessService;
import com.yifu.cloud.plus.v1.yifu.process.constant.ProcessConstants;
import com.yifu.cloud.plus.v1.yifu.process.entity.*;
import com.yifu.cloud.plus.v1.yifu.process.util.ProcessAuditUtil;
import com.yifu.cloud.plus.v1.yifu.process.vo.ProcessVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 流程审批抽象类——仿照crm流程处理
 * @author 陈宇茜
 * @date 2025/01/13
 * @since 1.7.5
 */
@Slf4j
public abstract class AbastractAuditProcess<T,E extends T> {

	@Resource
	protected TAuditNodeProcessService auditNodeProcessService;

	@Resource
	protected TAuditRecordService auditRecordService;

    public static final String BIGIN_NODE_NO_FOUND = "未找到开始审批节点，请联系管理员";
    public static final String NEXT_NODE_USER_NULL = "未查询到下个节点的用户，请联系管理员";
    public static final String NEXT_AUDIT_NODE_NOT_FOUND = "未查询到下一个审核节点，请联系管理员";

	@Autowired
	private ProcessDaprUtils processDaprUtils;

	@Autowired
	protected UpmsDaprUtils upmsDaprUtils;

    /**
     * 审核成功并结束逻辑
	 * @param entity 业务实体
	 * @param auditRecord 审批记录
	 * @param loginUser 当前登录用户
     * @return R<String>
     **/
    abstract public R<String> auditSuccess(T entity, TAuditRecord auditRecord, YifuUser loginUser);

    /**
	 * 审核成功并结束逻辑
	 * @param entity 业务实体
	 * @param auditRecord 审批记录
	 * @param remoteSysUserList 当前登录用户
	 * @return R<String>
     **/
    abstract public R<String> auditSuccessAndNex(T entity, List<SysUser> remoteSysUserList, TAuditRecord auditRecord);

    /**
	 * 审核不通过处理逻辑
	 * @param entity 业务实体
	 * @param approvalRecord 审批记录
	 * @return R<String>
     **/
    abstract public R<String> auditFail(T entity, TAuditRecord approvalRecord);

    /**
     * 选择节点。不同类型可能有不同选择节点
	 * @param entity 业务实体
     * @return TProcessNode
     **/
    abstract public TProcessNode choiceGetNode(ProcessVo processVo, List<TNodeRoute> nodeRouteList, List<TNodeRouteCondition> nodeRouteConditionList,
											   TProcessNode currentNode, T entity, String auditType, YifuUser loginUser);

    /**
     * 审批发消息
	 * @param users  发送人
     * @param entity 实体信息
     * @param type 1发送审批消息 2发送抄送消息
     * @return R<String>
     **/
    abstract public R<String> sendMessage(List<SysUser> users, T entity, String type, TAuditRecord approvalRecord);

	/**
	 * 根据事业部条线获取审批用户
	 * @param nodePrimission
	 * @param entity
	 * @return List<SysUser>
	 **/
    abstract public List<SysUser> getDivisionAuditUser(TNodePrimission nodePrimission, T entity);


    /**
     * 获取当前节点的审批人
	 *
	 * @param processVo 审批流程完整配置
	 * @param currentProcessNode 当前节点
     * @param departId    部门id
     * @param entityId    实体id
	 * @param auditType   审核类型 0不购买商险审核
     * @return List<SysUser>
     **/
    private List<SysUser> getAuditUseListByProcessNode(ProcessVo processVo, TProcessNode currentProcessNode, String departId, String entityId, String auditType,
													 T entity, TAuditRecord auditRecord) {
        // 定义审批用户
        List<TNodePrimission> nodePrimissionList = null;
        for (TProcessNode processNode : processVo.getProcessNodeList()) {
            if (StringUtils.equals(currentProcessNode.getLogoTitle(), processNode.getLogoTitle())) {
                nodePrimissionList = processNode.getNodePrimissionList();
            }
        }
        if (Common.isEmpty(nodePrimissionList)) {
            throw new CheckedException("未找到审批用户信息,请联系管理员");
        }
        // 获取所有审批用户
        List<SysUser> sysUserList = new ArrayList<>();
		// 节点是否允许跳过（0：不允许，1允许）
		Integer isPass = CommonConstants.ZERO_INT;
        for (TNodePrimission nodePrimission : nodePrimissionList) {
			isPass = CommonConstants.ZERO_INT;
			// 审核用户改造； 3指定用户;5指定角色(crm)
			if (CommonConstants.THREE_INT == nodePrimission.getType().intValue()
					|| CommonConstants.TWO_INT == nodePrimission.getType().intValue()
					|| CommonConstants.FIVE_INT == nodePrimission.getType().intValue()) {
				sysUserList = this.getDepartAuditUser(nodePrimission, departId);
			}
			// 6指定事业部配置表
			if (CommonConstants.SIX_INT == nodePrimission.getType().intValue()) {
				// 根据事业部条线获取审批用户
				sysUserList = this.getDivisionAuditUser(nodePrimission, entity);
			}

			// 事业部条线没有审批人直接审核通过,配置了可以跳过
			if(Common.isEmpty(sysUserList) && CommonConstants.ONE_STRING.equals(nodePrimission.getIsPass())){
				// 系统自动给当前节点完成审核，将审核通过
				return sysAutoAudit(processVo,currentProcessNode,departId,auditType,entityId,entity);
			} else {
				if (Common.isEmpty(sysUserList)) {
					throw new CheckedException("未找到审批用户");
				}
				// 微信审批通知发送
				sendMessage(sysUserList,entity,CommonConstants.ONE_STRING, auditRecord);
				for (SysUser sysUser : sysUserList) {
					// 新增指派审核流程记录
					TAuditRecord newEntity = new TAuditRecord();
					newEntity.setDomainId(entityId);
					newEntity.setFlowId(currentProcessNode.getProcessId());
					newEntity.setNodeId(currentProcessNode.getId());
					newEntity.setApprovalMan(String.valueOf(sysUser.getUserId()));
					newEntity.setApprovalManName(sysUser.getNickname());
					newEntity.setDeleteFlag(CommonConstants.NOT_DELETE_FLAG);
					newEntity.setPreFlag(CommonConstants.ONE_STRING);
					newEntity.setApprovalResult(CommonConstants.TWO_STRING);
					newEntity.setNodeName(currentProcessNode.getName());
					// 获取提交人信息
					TAuditRecord tAuditRecord = auditRecordService.getOne(Wrappers.<TAuditRecord>query().lambda().eq(TAuditRecord::getDomainId, entityId)
							.eq(TAuditRecord::getAuditType, auditType)
							.eq(TAuditRecord::getPreFlag, CommonConstants.ONE_STRING)
							.eq(TAuditRecord::getApprovalResult, CommonConstants.THREE_STRING)
							.orderByDesc(TAuditRecord::getId).last(CommonConstants.SQL_LIMIT_ONE));
					if(Common.isNotNull(tAuditRecord)) {
						newEntity.setSubmitMan(tAuditRecord.getSubmitMan());
						newEntity.setSubmitManName(tAuditRecord.getSubmitManName());
						newEntity.setSubmitCreateTime(tAuditRecord.getSubmitCreateTime());
						newEntity.setReason(tAuditRecord.getReason());
						newEntity.setEntityName(tAuditRecord.getEntityName());
						newEntity.setAuditType(tAuditRecord.getAuditType());
					}
					newEntity.setCreateTime(LocalDateTime.now());
					auditRecordService.save(newEntity);
				}

			}
        }
		// 事业部条线没有审批人直接审核通过,配置了可以跳过
		if(Common.isEmpty(sysUserList) && isPass == CommonConstants.ONE_INT){
			sysUserList = new ArrayList<>();
			SysUser sysUserTemp = new SysUser();
			sysUserList.add(sysUserTemp);
		}

        return sysUserList;
    }


    /**
     * 提交审核：获取审核人
	 * @param entityId    实体id
     * @param loginUser   当前登录人
     * @param departId    部门id      通过该部门获取审批流程
     * @param processType 流程类型 1不购买商险申请
     * @param auditType   审核类型 0不购买商险审核
	 * @param reason      申请原因（非必填）
	 * @param entityName  实体标识信息
     * @return R<List<SysUser>>
     **/
    public R<List<SysUser>> getAuditUserList(String entityId, YifuUser loginUser, String departId, String processType, String auditType,
												String reason, String entityName, T entity, Class<T> clazz) {
        // 获取审批流程完整配置
        ProcessVo processVo = this.getProcessVoByType(processType);
        if (Common.isEmpty(processVo)) {
            throw new CheckedException("未找到满足条件的主流程,请联系管理员");
        }
        // 获取开始节点
        TProcessNode startProcessNode = ProcessAuditUtil.getBeginProcessNode(processVo);
        if (Common.isEmpty(startProcessNode)) {
            return R.failed(BIGIN_NODE_NO_FOUND);
        }
        String startNodeLogo = startProcessNode.getLogoTitle();
        // 保存TAuditNodeProcess节点信息
        saveNodeProcess(processVo, startNodeLogo, entityId, auditType);
        // 获取开始节点下一个审核节点
        TProcessNode nextProcessNode = getNextNode(processVo, startNodeLogo, entityId, auditType, entity, loginUser);
        if (Common.isEmpty(nextProcessNode)) {
            throw new CheckedException(NEXT_AUDIT_NODE_NOT_FOUND);
        }

        // 记录提交审核日志
        TAuditRecord submitAuditRecord = new TAuditRecord();
        submitAuditRecord.setDomainId(entityId);
        submitAuditRecord.setFlowId(startProcessNode.getProcessId());
        submitAuditRecord.setNodeId(startProcessNode.getId());
        submitAuditRecord.setApprovalMan(String.valueOf(loginUser.getId()));
        submitAuditRecord.setApprovalManName(loginUser.getNickname());
        // 审批结果为“提交”
        submitAuditRecord.setApprovalResult(CommonConstants.dingleDigitStrArray[3]);
        submitAuditRecord.setDeleteFlag(CommonConstants.NOT_DELETE_FLAG);
        submitAuditRecord.setApprovalTime(LocalDateTime.now());
		// 审核记录标识 1当前审核记录
        submitAuditRecord.setPreFlag(CommonConstants.ONE_STRING);
        submitAuditRecord.setSubmitMan(String.valueOf(loginUser.getId()));
        submitAuditRecord.setSubmitManName(loginUser.getNickname());
        // 申请原因
        submitAuditRecord.setReason(reason);
        // 审核类型
        submitAuditRecord.setAuditType(auditType);
        submitAuditRecord.setCreateTime(LocalDateTime.now());
        // 提交节点名称
        submitAuditRecord.setNodeName(startProcessNode.getName());
        submitAuditRecord.setSubmitCreateTime(LocalDateTime.now());
        submitAuditRecord.setEntityName(entityName);
        auditRecordService.save(submitAuditRecord);

        // 获取节点审核人
        List<SysUser> remoteSysUserList = getAuditUseListByProcessNode(processVo, nextProcessNode, departId, entityId, auditType, entity, submitAuditRecord);
        if (Common.isEmpty(remoteSysUserList)) {
            throw new CheckedException(NEXT_NODE_USER_NULL);
        }
        return new R<>(remoteSysUserList);

    }

    /**
     * 审核并提交下一个节点：获取下一个审核人
	 * @param entityId             实体id
     * @param approvalResult    审核标识 0审核通过 其他审核不通过
     * @param approvalOpinion 审核意见
     * @param loginUser      当前登录人
     * @param auditType      审核类型 0不购买商险审核
     * @param entity         实体类：用于审核通过逻辑
     * @return R<String>
     **/
    public R<String> auditUserList(String entityId, String approvalResult, String approvalOpinion, YifuUser loginUser,
								   String auditType, T entity, String departId) {
        String loginUserId = loginUser.getId();
        // 判断当前审核是否为最新待审核记录
        List<TAuditRecord> auditRecordList = auditRecordService.list
                (Wrappers.<TAuditRecord>query().lambda().eq(TAuditRecord::getDomainId, entityId)
                        .eq(TAuditRecord::getAuditType, auditType)
                        .eq(TAuditRecord::getDeleteFlag, CommonConstants.NOT_DELETE_FLAG)
                        .eq(TAuditRecord::getApprovalResult, CommonConstants.TWO_STRING)
                        .eq(TAuditRecord::getApprovalMan, loginUserId));
        if (auditRecordList.size() != CommonConstants.ONE_INT) {
            return R.failed("当前用户不能审核该记录");
        }

        // 更新审核记录信息
        TAuditRecord auditRecord = auditRecordList.get(0);
		auditRecord.setApprovalResult(approvalResult);
		auditRecord.setApprovalOpinion(approvalOpinion);
		auditRecord.setApprovalTime(LocalDateTime.now());
        auditRecordService.updateById(auditRecord);
        // 移除同一个节点的另外审批人。多个节点一个人审批就够了,其他都移除
        auditRecordService.remove(Wrappers.<TAuditRecord>query().lambda()
                .eq(TAuditRecord::getDomainId, entityId)
                .eq(TAuditRecord::getAuditType, auditType)
                .isNull(TAuditRecord::getApprovalTime));

        // 审核通过处理
        if (CommonConstants.ZERO_STRING.equals(approvalResult)) {
            // 获取流程，并判断是否是最后一个节点
            // 获取流程的主流程
            TAuditNodeProcess auditNodeProocess = auditNodeProcessService.getOne(Wrappers.<TAuditNodeProcess>query().lambda()
                    .eq(TAuditNodeProcess::getDomainId, entityId)
                    .eq(TAuditNodeProcess::getType, auditType)
                    .eq(TAuditNodeProcess::getMainType, CommonConstants.ZERO_STRING)
					.eq(TAuditNodeProcess::getDeleteFlag, CommonConstants.NOT_DELETE_FLAG)
                    .orderByDesc(TAuditNodeProcess::getId)
                    .last(CommonConstants.SQL_LIMIT_ONE));
            if (auditNodeProocess == null) {
                throw new CheckedException("未获取到审批记录流程数据");
            }
			// 改成dapr获取
            ProcessVo processVo = this.getProcessVoById(auditNodeProocess.getProcessId());
            TProcessNode endProcessNode = ProcessAuditUtil.getEndProcessNode(processVo);
			if (endProcessNode == null) {
				throw new CheckedException("未获取到结束节点");
			}
			TProcessNode preEndProcessNode = ProcessAuditUtil.getPreEndTProcessNode(processVo, endProcessNode);
			if (preEndProcessNode == null) {
				throw new CheckedException("未找到结束节点前一个节点");
			}
			// 当前是结束节点前的一个节点
			if (StringUtils.equals(preEndProcessNode.getId(), auditRecord.getNodeId())) {
				// 走审核通过处理
				return auditSuccess(entity, auditRecord, loginUser);
			} else {
				TProcessNode currentProcessNode = ProcessAuditUtil.getCurrentProcessNode(processVo, auditRecord.getNodeId());
                TProcessNode nextProcessNode = getNextNode(processVo, currentProcessNode.getLogoTitle(), entityId, auditType, entity, loginUser);
				if (nextProcessNode == null) {
					throw new CheckedException(NEXT_AUDIT_NODE_NOT_FOUND);
				}
                auditNodeProocess = auditNodeProcessService.getOne(Wrappers.<TAuditNodeProcess>query().lambda()
                                .eq(TAuditNodeProcess::getDomainId, entityId)
                                .eq(TAuditNodeProcess::getType, auditType)
                                .eq(TAuditNodeProcess::getMainType, CommonConstants.ZERO_STRING)
                                .eq(TAuditNodeProcess::getDeleteFlag, CommonConstants.NOT_DELETE_FLAG)
                                .orderByDesc(TAuditNodeProcess::getId)
                                .last(CommonConstants.SQL_LIMIT_ONE));
				// 如果返回的是end节点：判断是不是返回的是不是主流程结束节点
				if (StringUtils.equals(ProcessConstants.PROCESS_NODE_END, nextProcessNode.getType())
						&& StringUtils.equals(auditNodeProocess.getProcessId(), nextProcessNode.getProcessId())) {
					// 审核通过流程
					return auditSuccess(entity, auditRecord, loginUser);
				}
				// 获取审批用户
				List<SysUser> remoteSysUserList = getAuditUseListByProcessNode(processVo,nextProcessNode, departId, entityId, auditType, entity, auditRecord);
				if (Common.isEmpty(remoteSysUserList)) {
					throw new CheckedException(NEXT_NODE_USER_NULL);
				}
				// 流程中的审核结束，继续下一个节点
				return auditSuccessAndNex(entity, remoteSysUserList, auditRecord);
            }
        } else {
            //审核不通过处理
            return auditFail(entity, auditRecord);
        }
    }

	/**
	 * 获取下一个节点信息
	 * @param processVo 当前流程配置信息
	 * @param currentNodeLogo 当前节点标识
	 * @param entityId 实体ID
	 * @param auditType   审核类型 0不购买商险审核
	 * @param entity   实体信息
	 * @param loginUser  登录人信息
	 * @return TProcessNode
	 **/
    private TProcessNode getNextNode(ProcessVo processVo, String currentNodeLogo, String entityId, String auditType, T entity, YifuUser loginUser) {

        // 获取已经过的节点信息
        TAuditNodeProcess auditNodeProcess = auditNodeProcessService.getOne(Wrappers.<TAuditNodeProcess>query().lambda()
                .eq(TAuditNodeProcess::getDomainId, entityId)
                .eq(TAuditNodeProcess::getType, auditType)
                .eq(TAuditNodeProcess::getDeleteFlag, CommonConstants.ZERO_STRING)
                .isNotNull(TAuditNodeProcess::getLogoTitle)
                .orderByDesc(TAuditNodeProcess::getId).last(CommonConstants.SQL_LIMIT_ONE));
        if (Common.isNotNull(auditNodeProcess) && !StringUtils.equals(currentNodeLogo, auditNodeProcess.getLogoTitle())) {
            throw new CheckedException("记录的流程节点和当前执行节点不匹配");
        }
        // 当前流程配置节点信息
        List<TProcessNode> processNodeList = processVo.getProcessNodeList();
		// 当前流程配置路由信息
        List<TNodeRoute> nodeRouteList = processVo.getNodeRouteList();
        // 判断当前节点类型,如果是选择节点则进行条件表达式判断判断
        TProcessNode currentNode = null;
        for (TProcessNode processNode : processNodeList) {
            if (StringUtils.equals(currentNodeLogo, processNode.getLogoTitle())) {
                currentNode = processNode;
            }
        }
        if (Common.isEmpty(currentNode)) {
            throw new CheckedException("未获取到当前节点");
        }
		// 当前节点为选择节点,获取当前节点路由类型
        if (StringUtils.equals(ProcessConstants.PROCESS_NODE_TYPE_CHOICE, currentNode.getType())) {
            List<TNodeRouteCondition> nodeRouteConditionList = Lists.newArrayList();
            for (TNodeRoute nodeRoute : nodeRouteList) {
            	// 获取选择节点下的判断分支信息存到nodeRouteConditionList
                if (StringUtils.equals(currentNode.getLogoTitle(), nodeRoute.getPrewNode())) {
                    nodeRouteConditionList.addAll(nodeRoute.getNodeRouteConditionList());
                }
            }
            // 根据判断条件获取下一个审批节点信息
            return choiceGetNode(processVo, nodeRouteList, nodeRouteConditionList, currentNode, entity, auditType, loginUser);
        } else if (StringUtils.equals(ProcessConstants.PROCESS_NODE_END, currentNode.getType())) {
        	// 当前到了结束节点
			TProcessNode endNode = ProcessAuditUtil.getEndProcessNode(processVo);
			if (StringUtils.equals(currentNode.getId(), endNode.getId())) {
				return endNode;
			} else {
				throw new CheckedException("当前不是结束节点");
			}
        } else if (StringUtils.equals(ProcessConstants.PROCESS_NODE_BEGIN, currentNode.getType())
				|| StringUtils.equals(ProcessConstants.PROCESS_NODE_SERVICE, currentNode.getType())) {
			// 当前是开始节点或者服务节点
            try {
				// 查找节点后的路由信息
                TNodeRoute nexNodeRoute = ProcessAuditUtil.getNexTNodeRoute(nodeRouteList, currentNodeLogo);
                // 存下一个节点的信息
                saveNodeProcess(processVo, nexNodeRoute.getNextNode(), entityId, auditType);
                // 校验即将进入的节点信息，是审批节点返回节点信息，不是继续找下一个节点信息
                return validateNextNode(processVo, nexNodeRoute.getNextNode(), entityId, nexNodeRoute.getRouteType(), auditType, entity, loginUser);
            }catch (Exception e){
				// todo 优化报错展示形式
               throw e;
            }
        } else {
            throw new CheckedException("未知的流程节点类型");
        }
    }

    /**
     * 校验即将进入的节点信息，是审批节点返回节点信息，不是继续找下一个节点信息
	 * @param processVo       流程配置信息
     * @param currentNodeLogo 当前节点标识
     * @param entityId        实体id
     * @param preRouteType       上一个路由类型
	 * @param auditType       审核类型 0不购买商险审核
     * @return TProcessNode
     **/
    protected TProcessNode validateNextNode(ProcessVo processVo, String currentNodeLogo, String entityId, String preRouteType, String auditType,
											   T entity, YifuUser loginUser) {
    	// 获取节点配置信息
        List<TProcessNode> processNodeList = processVo.getProcessNodeList();
        // 获取即将进入的节点信息
        TProcessNode currentNode = null;
        for (TProcessNode processNode : processNodeList) {
            if (StringUtils.equals(currentNodeLogo, processNode.getLogoTitle())) {
                currentNode = processNode;
            }
        }
        if(Common.isEmpty(currentNode)){
			throw new CheckedException("未获取到当前节点，请联系管理员处理");
		}
        // 即将进入的节点是选择判断节点，继续往找下一个节点信息
        if (StringUtils.equals(ProcessConstants.PROCESS_NODE_TYPE_CHOICE, currentNode.getType())) {
            return getNextNode(processVo, currentNodeLogo, entityId, auditType, entity, loginUser);
        } else if (StringUtils.equals(ProcessConstants.PROCESS_NODE_SERVICE, currentNode.getType())) {
			// 即将进入的节点是选择服务节点，继续根据路由判断
            if (StringUtils.equals(preRouteType, CommonConstants.ONE_STRING)) {
                // 即将进入的节点是审批节点，返回节点信息
                return currentNode;
            } else if (StringUtils.equals(preRouteType, CommonConstants.THREE_STRING)) {
                // 1.7.5 未引入抄送逻辑
                // 即将进入的节点是抄送节点，继续找下一个节点
				return getNextNode(processVo, currentNode.getLogoTitle(), entityId, auditType, entity, loginUser);
            } else {
                throw new CheckedException("未知的节点");
            }
        } else if (StringUtils.equals(ProcessConstants.PROCESS_NODE_BEGIN, currentNode.getType())) {
            return getNextNode(processVo, currentNode.getLogoTitle(), entityId, auditType, entity, loginUser);
        } else if (StringUtils.equals(ProcessConstants.PROCESS_NODE_END, currentNode.getType())) {
            return getNextNode(processVo, currentNode.getLogoTitle(), entityId, auditType, entity, loginUser);
        } else if (StringUtils.equals(ProcessConstants.PROCESS_NODE_EMBED, currentNode.getType())) {
            return getNextNode(processVo, currentNode.getLogoTitle(), entityId, auditType, entity, loginUser);
        } else {
            throw new CheckedException("未知的节点");
        }
    }

    /**
     * 保存经过流程节点记录
	 * @param processVo 当前流程配置信息
     * @param currentNodeLogo 当前节点标识
     * @param entityId 实体ID
	 * @param type 审核类型 0不购买商险审核
     **/
    protected void saveNodeProcess(ProcessVo processVo, String currentNodeLogo, String entityId, String type) {
    	// 当前节点的信息
        TProcessNode processNode = null;
        for (TProcessNode node : processVo.getProcessNodeList()) {
            if (StringUtils.equals(currentNodeLogo, node.getLogoTitle())) {
                processNode = node;
            }
        }
        // todo 优化报错展示形式
        if (Common.isEmpty(processNode)) {
            throw new CheckedException("保存经过流程节点记录时，节点信息未找到");
        }
        // 保存本次节点记录
        TAuditNodeProcess auditNodeProcess = new TAuditNodeProcess();
		auditNodeProcess.setDomainId(entityId);
		auditNodeProcess.setNodeId(processNode.getId());
		auditNodeProcess.setProcessId(processNode.getProcessId());
		auditNodeProcess.setCreateTime(LocalDateTime.now());
		// 新版流程审批默认主节点
		auditNodeProcess.setMainType(CommonConstants.ZERO_STRING);
		auditNodeProcess.setLogoTitle(processNode.getLogoTitle());
		auditNodeProcess.setNodeType(processNode.getType());
		auditNodeProcess.setNodeName(processNode.getName());
		auditNodeProcess.setProcessName(processVo.getName());
		auditNodeProcess.setDeleteFlag(CommonConstants.ZERO_STRING);
		auditNodeProcess.setType(type);
		auditNodeProcessService.save(auditNodeProcess);
    }

	/**
	 * 根据流程类型查询ProcessVo
	 * @param processType 流程类型
	 * @return R<ProcessVo>
	 * @since mvp1.7.5
	 **/
	private ProcessVo getProcessVoByType(String processType) {
		// 改成dapr请求
		R<ProcessVo> processVoR = processDaprUtils.getProcessVoByType(processType);
		if (processVoR == null) {
			throw new CheckedException("调用流程服务返回为空");
		}
		if (CommonConstants.SUCCESS != processVoR.getCode()) {
			throw new CheckedException("调用流程服务返回失败");
		}
		ProcessVo processVo = processVoR.getData();
		if (processVo == null) {
			throw new CheckedException("调用流程服务返回数据为空");
		}
		return processVo;
	}

	/**
	 * 根据流程Id查询ProcessVo
	 * @param processId 流程Id
	 * @return R<ProcessVo>
	 * @since mvp1.7.5
	 **/
	private ProcessVo getProcessVoById(String processId) {
		// 改成dapr请求
		R<ProcessVo> processVoR = processDaprUtils.getProcessVoById(processId);
		if (processVoR == null) {
			throw new CheckedException("调用流程服务返回为空");
		}
		if (CommonConstants.SUCCESS != processVoR.getCode()) {
			throw new CheckedException("调用流程服务返回失败");
		}
		ProcessVo processVo = processVoR.getData();
		if (processVo == null) {
			throw new CheckedException("调用流程服务返回数据为空");
		}
		return processVo;
	}

	/**
	 * 获取部门审核人
	 * @param nodePrimission 审批角色
	 * @param departId       部门ID
	 * @return List<SysUser>
	 **/
	private List<SysUser> getDepartAuditUser(TNodePrimission nodePrimission, String departId) {
		List<SysUser> remoteSysUserList = new ArrayList<>();
		if (CommonConstants.THREE_INT == nodePrimission.getType().intValue()) {
			// 3.指定用户
			if (Common.isEmpty(nodePrimission.getUser())) {
				throw new CheckedException("未查询当前流程权限对应的用户");
			}
			// 通过用户id查询,查找当前用户
			R<SysUser> simpleUser = upmsDaprUtils.getSimpleUser(nodePrimission.getUser());
			if(null != simpleUser && null != simpleUser.getData()) {
				remoteSysUserList.add(simpleUser.getData());
			}
		}  else if (CommonConstants.FIVE_INT == nodePrimission.getType().intValue()){
			// 5.指定角色(crm)
			if (Common.isEmpty(nodePrimission.getApprovalRole())) {
				throw new CheckedException("未查询当前节点配置的审核角色");
			}
			UserApprovalRoleVO userByApprovalRole = new UserApprovalRoleVO();
			userByApprovalRole.setDepartId(departId);
			userByApprovalRole.setRoleId(nodePrimission.getApprovalRole());
			R<SysUserListVo> simpleUserList = upmsDaprUtils.getUserByRoleIdForCrm(userByApprovalRole);
			if(null != simpleUserList && null != simpleUserList.getData()) {
				remoteSysUserList = simpleUserList.getData().getUserList();
			}
		}
		return remoteSysUserList;
	}

	/**
	 * 系统自动审核
	 * @param entityId             实体id
	 * @param auditType      审核类型 0不购买商险审核
	 * @param entity         实体类：用于审核通过逻辑
	 * @return R<String>
	 **/
	private List<SysUser> sysAutoAudit(ProcessVo processVo,TProcessNode currentProcessNode,String departId, String auditType,
							  String entityId,T entity) {
		// 新增自动审核通过记录
		TAuditRecord newEntity = new TAuditRecord();
		newEntity.setDomainId(entityId);
		newEntity.setFlowId(currentProcessNode.getProcessId());
		newEntity.setNodeId(currentProcessNode.getId());
		newEntity.setApprovalMan(CommonConstants.ONE_STRING);
		newEntity.setApprovalManName("审核人为空，系统默认审核通过");
		newEntity.setApprovalOpinion("审核人为空，默认审核通过");
		newEntity.setApprovalTime(LocalDateTime.now());
		newEntity.setDeleteFlag(CommonConstants.NOT_DELETE_FLAG);
		newEntity.setPreFlag(CommonConstants.ONE_STRING);
		newEntity.setApprovalResult(CommonConstants.ZERO_STRING);
		newEntity.setNodeName(currentProcessNode.getName());
		// 获取提交人信息
		TAuditRecord tAuditRecord = auditRecordService.getOne(Wrappers.<TAuditRecord>query().lambda()
				.eq(TAuditRecord::getDomainId, entityId)
				.eq(TAuditRecord::getAuditType, auditType)
				.eq(TAuditRecord::getPreFlag, CommonConstants.ONE_STRING)
				.eq(TAuditRecord::getApprovalResult, CommonConstants.THREE_STRING)
				.orderByDesc(TAuditRecord::getId).last(CommonConstants.SQL_LIMIT_ONE));
		if(Common.isNotNull(tAuditRecord)) {
			newEntity.setSubmitMan(tAuditRecord.getSubmitMan());
			newEntity.setSubmitManName(tAuditRecord.getSubmitManName());
			newEntity.setSubmitCreateTime(tAuditRecord.getSubmitCreateTime());
			newEntity.setReason(tAuditRecord.getReason());
			newEntity.setEntityName(tAuditRecord.getEntityName());
			newEntity.setAuditType(tAuditRecord.getAuditType());
		}
		newEntity.setCreateTime(LocalDateTime.now());
		auditRecordService.save(newEntity);

		// 获取流程配置信息
		TProcessNode endProcessNode = ProcessAuditUtil.getEndProcessNode(processVo);
		if (endProcessNode == null) {
			throw new CheckedException("系统自动审核,未获取到结束节点");
		}
		TProcessNode preEndProcessNode = ProcessAuditUtil.getPreEndTProcessNode(processVo, endProcessNode);
		if (preEndProcessNode == null) {
			throw new CheckedException("系统自动审核,未找到结束节点前一个节点");
		}
		// 当前是结束节点前的一个节点
		if (StringUtils.equals(preEndProcessNode.getId(), newEntity.getNodeId())) {
			// 直接最终审核通过
			auditSuccess(entity, newEntity, null);
			return null;
		} else {
			TProcessNode nextProcessNode = getNextNode(processVo, currentProcessNode.getLogoTitle(), entityId, auditType, entity, null);
			if (nextProcessNode == null) {
				// 未找到下一个审核节点，删除系统自动审核的记录
				auditRecordService.removeById(newEntity.getId());
				throw new CheckedException("未找到系统自动审核后，下一个审批节点，请联系管理员");
			}
			// 如果返回的是end节点：判断是不是返回的是不是主流程结束节点
			if (StringUtils.equals(ProcessConstants.PROCESS_NODE_END, nextProcessNode.getType())
					&& StringUtils.equals(currentProcessNode.getProcessId(), nextProcessNode.getProcessId())) {
				// 直接最终审核通过
				auditSuccess(entity, newEntity, null);
				return null;
			}
			// 获取下个审批用户
			List<SysUser> remoteSysUserList = getAuditUseListByProcessNode(processVo,nextProcessNode, departId, entityId, auditType, entity, newEntity);
			if (Common.isEmpty(remoteSysUserList)) {
				// 未找到下一个审核节点，删除系统自动审核的记录
				auditRecordService.removeById(newEntity.getId());
				throw new CheckedException("未找到系统自动审核后，下个节点的审批用户");
			}
			return remoteSysUserList;
		}

	}
}
