package com.xdap.self_development.service.impl;

import com.alibaba.fastjson2.JSON;
import com.xdap.api.moudle.user.pojo.XdapUsers;
import com.xdap.self_development.common.BusinessDatabase;
import com.xdap.self_development.controller.form.ApprovalUserNodeDTO;
import com.xdap.self_development.controller.form.HandleApprovalRequest;
import com.xdap.self_development.controller.form.HandleReturnNodeForm;
import com.xdap.self_development.controller.form.UpdateNodeForm;
import com.xdap.self_development.controller.request.ApprovalNodeRequest;
import com.xdap.self_development.domain.dto.*;
import com.xdap.self_development.domain.enums.*;
import com.xdap.self_development.domain.pojo.*;
import com.xdap.self_development.domain.view.FlowNode;
import com.xdap.self_development.exception.CommonException;
import com.xdap.self_development.service.*;
import com.xdap.self_development.utils.RedisLockUtils;
import groovy.util.logging.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.text.Collator;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 工作流审批服务实现类
 *
 * @version 1.0
 * @since 2025
 */
@Service
@Slf4j
public class ActivitiProcessServiceImpl implements ActivitiProcessService {
    @Resource
    private DataEntryEngineModelService dataEntryEngineModelService;
    @Resource
    private EngineParamDetailService engineParamDetailService;
    @Resource
    private XdapDeptUsersService xdapDeptUsersService;
    @Resource
    private TemplateApprovalService templateApprovalService;
    @Resource
    private BusinessDatabase bd;
    @Resource
    private RedisLockUtils redisLockUtil;
    @Resource
    private ActivitiProcessService myself;
    @Resource
    private com.xdap.runtime.service.RuntimeAppContextService runtimeAppContextService;

    private static final String FLOW_LOCK_PREFIX = "data:lock:";
    private static final int FLOW_LOCK_EXPIRE_SECONDS = 5;

    private Comparator<String> getPartsNameComparator() {
        Collator collator = Collator.getInstance(Locale.CHINA);
        return (a, b) -> {
            if ("/".equals(a) && !"/".equals(b)) {
                return -1;
            }
            if (!"/".equals(a) && "/".equals(b)) {
                return 1;
            }
            return collator.compare(a, b);
        };
    }


    private static List<String> getStrings(EngineReviewListPojo reviewListPojo) {
        if (reviewListPojo == null || Objects.equals(reviewListPojo.getStatusCode(), ParamValueVersionEnum.REFUSE.getCode())
                || Objects.equals(reviewListPojo.getStatusCode(), ParamValueVersionEnum.PASSED.getCode())) {
            throw new CommonException("无效的审批记录请检查是否已经审批完成或被拒绝");
        }
        String currentAssignees = reviewListPojo.getApproverPersons();
        return Arrays.asList(currentAssignees.split(","));
    }

    /**
     * 发起审批流程 - 初始化审批数据
     * 根据机型ID和用户ID查找待审批的参数数据，生成变更说明并返回给前端显示
     *
     * @param modelID 发动机型号ID
     * @param userID  用户ID
     * @return 包含审批数据的DTO列表
     */
    @Override
    @Transactional
    public List<ActivitiDataDTO> initiateApproval(String modelID, String userID) {
        // 通过机型ID查找参数过滤更新的
        List<EngineParamDetailPojo> engineParamDetailPojos;
        try {
            engineParamDetailPojos = engineParamDetailService.selectByModelNewVersion(modelID).stream()
                    .filter(x -> ParamOperationEnum.UPDATE.toString().equals(x.getOperation())
                            && userID.equals(x.getLastUpdatedBy() == null ? "" : x.getLastUpdatedBy()))
                    .collect(Collectors.toList());
            if (ObjectUtils.isEmpty(engineParamDetailPojos)) {
                throw new CommonException("");
            }
        } catch (Exception e) {
            throw new CommonException("找不到机型ID对应的参数或机型参数里最新版本没有UPDATE的数据");
        }
        List<ActivitiDataDTO> activitiDataDTOS = new ArrayList<>();
        ArrayList<DataChangeCommentPojo> das = new ArrayList<>();
        for (EngineParamDetailPojo engineParamDetailPojo : engineParamDetailPojos) {
            String parameterId = engineParamDetailPojo.getParameterId();
            List<ParameterPojo> parameters = bd.getBusinessDatabase()
                    .eq("id", parameterId)
                    .doQuery(ParameterPojo.class);
            if (ObjectUtils.isEmpty(parameters)) {
                throw new CommonException("未找到对应参数模板中的参数");
            }
            ParameterPojo parameter = parameters.get(0);
            String com = "";
            String operation = engineParamDetailPojo.getOperation();
            if (ParamOperationEnum.UPDATE.toString().equals(operation)) {
                String parameterValue = StringUtils.isEmpty(engineParamDetailPojo.getParameterValue()) ?
                        "" : engineParamDetailPojo.getParameterValue();
                if (ObjectUtils.isEmpty(parameterValue)) {
                    com = "填写为:" + engineParamDetailPojo.getMinorVersion();
                } else {
                    com = "修改:" + parameterValue + "改为" + engineParamDetailPojo.getMinorVersion();
                }
            }
            if (ParamOperationEnum.INSERT.toString().equals(operation)) {
                com = "新增";
            }
            if (ParamOperationEnum.DELETE.toString().equals(operation)) {
                com = "删除";
            }
            DataEntryEngineModelPojo modelPojo = dataEntryEngineModelService.selectBymodelId(engineParamDetailPojo.getEngineModelId());
            if (ObjectUtils.isEmpty(modelPojo)) {
                throw new CommonException("该发动机型号不存在");
            }
            ActivitiDataDTO activitiDataDTO = new ActivitiDataDTO();
            BeanUtils.copyProperties(engineParamDetailPojo, activitiDataDTO);
            activitiDataDTO.setParameterValue(engineParamDetailPojo.getMinorVersion());
            activitiDataDTO.setChangeComment(com);
            activitiDataDTO.setEngineModelName(modelPojo.getModelName());
            activitiDataDTO.setPartsName(parameter.getPartsName());

            DataChangeCommentPojo dataChangeCommentPojo = new DataChangeCommentPojo();
            BeanUtils.copyProperties(engineParamDetailPojo, dataChangeCommentPojo, "id");
            dataChangeCommentPojo.setPartsName(parameter.getPartsName());
            dataChangeCommentPojo.setParamDetailId(engineParamDetailPojo.getId());
            dataChangeCommentPojo.setChangeComment(com);
            dataChangeCommentPojo.setUnit(parameter.getUnit());
            dataChangeCommentPojo.setParameterValue(engineParamDetailPojo.getMinorVersion());
            dataChangeCommentPojo.setCreatedBy(userID);
            dataChangeCommentPojo.setCreationDate(Timestamp.valueOf(LocalDateTime.now()));

            activitiDataDTOS.add(activitiDataDTO);
            das.add(dataChangeCommentPojo);
        }
        bd.getBusinessDatabase().doBatchInsert(das);
        return sortValueChange(activitiDataDTOS);
    }

    /**
     * 开始审批流程
     * 创建审批记录、分配待办任务、设置审批环节配置等
     *
     * @param approvalNodeRequest 审批节点请求对象，包含审批配置信息
     */
    @Override
    public void startActiviti(ApprovalNodeRequest approvalNodeRequest) {
        String processTitle = approvalNodeRequest.getProcessTitle();
        String userId = approvalNodeRequest.getUserId();
        // 1. 获取第一个审批环节（按nodeOrder排序取最小）
        ApprovalNodeDTO firstNode = approvalNodeRequest.getNodeList().stream()
                .min(Comparator.comparingInt(ApprovalNodeDTO::getNodeOrder))
                .orElseThrow(() -> new RuntimeException("审批环节配置不能为空"));

        DataEntryEngineModelPojo model = bd.getBusinessDatabase()
                .eq("id", approvalNodeRequest.getModelId())
                .doQueryFirst(DataEntryEngineModelPojo.class);
        if (ObjectUtils.isEmpty(model)) {
            throw new CommonException("机型不存在，请检查");
        }
        // 检查当前参数是否全部填写完成
        TodoTaskPojo filledTodo = bd.getBusinessDatabase()
                .eq("model_id", model.getId())
                .eq("data_type", CurrentNodeEnum.REPAIR.getDesc())
                .eq("is_delete", 0)
                .eq("owner_id", userId)
                .eq("process_title", model.getModelName() + "-" + "填写参数任务")
                .doQueryFirst(TodoTaskPojo.class);
        if (filledTodo != null) {
            List<EngineParamDetailPojo> toBeFilledParams = bd.getBusinessDatabase()
                    .eq("engine_model_id", model.getId())
                    .eq("major_version", model.getVersionNumber())
                    .eq("filled_by", userId)
                    .isNull("minor_version")
                    .in("version_status", Arrays.asList(1, null))
                    .doQuery(EngineParamDetailPojo.class);
            if (!ObjectUtils.isEmpty(toBeFilledParams)) {
                StringBuilder errorMsg = new StringBuilder("填写人在当前机型的参数未全部填写完成，请检查：\n");
                for (EngineParamDetailPojo param : toBeFilledParams) {
                    errorMsg.append(param.getSubsystemName())
                            .append("-")
                            .append(param.getPartsName())
                            .append("-")
                            .append(param.getParameterName())
                            .append("\n");
                }
                throw new CommonException(errorMsg.toString());
            }
        }

        // 查询机型最新版本的参数，过滤出操作为更新且由当前用户更新的参数
        List<EngineParamDetailPojo> paramList = bd.getBusinessDatabase()
                .eq("engine_model_id", model.getId())
                .eq("major_version", model.getVersionNumber())
                .eq("last_updated_by", userId)
                .doQuery(EngineParamDetailPojo.class);

        if (paramList.isEmpty()) {
            throw new CommonException("没有找到您需要填写的参数");
        }

        //获取提交人
        XdapUsers xdapUsers = xdapDeptUsersService.selectUserByID(userId);
        String createBy = ObjectUtils.isNotEmpty(xdapUsers) ? xdapUsers.getUsername() : null;
        String approvalId = UUID.randomUUID().toString();

        if (approvalNodeRequest.getFlowId() != null && !approvalNodeRequest.getFlowId().isEmpty()) {
            // 清除拒绝提醒待办
            bd.getBusinessDatabase()
                    .eq("document_no", approvalNodeRequest.getFlowId())
                    .eq("data_type", "数据拒绝")
                    .update("is_delete", 1)
                    .doUpdate(TodoTaskPojo.class);
        }

        // 创建发动机审核列表POJO对象
        EngineReviewListPojo engineReviewListPojo = new EngineReviewListPojo();
        engineReviewListPojo.setId(approvalId);
        engineReviewListPojo.setModelId(model.getId());
        engineReviewListPojo.setModelName(model.getModelName());
        engineReviewListPojo.setYcOrOth(model.getYcOrOth());
        engineReviewListPojo.setProcessTopic(processTitle);
        engineReviewListPojo.setStatusCode(ParamValueVersionEnum.UNDER.getCode());
        engineReviewListPojo.setApplicant(userId);
        engineReviewListPojo.setStatusDescription(ParamValueVersionEnum.UNDER.getDesc());
        engineReviewListPojo.setNodeName(firstNode.getNodeName());
        engineReviewListPojo.setApproverPersons(String.join(",", firstNode.getAssignees()));
        engineReviewListPojo.setReviewComment(approvalNodeRequest.getComment());
        engineReviewListPojo.setCreationDate(Timestamp.valueOf(LocalDateTime.now()));
        engineReviewListPojo.setCreatedBy(userId);
        engineReviewListPojo.setObjectVersionNumber(model.getVersionNumber());

        engineReviewListPojo.setReturnNum(0);
        engineReviewListPojo.setPreNode(-1);
        bd.getBusinessDatabase().doInsert(engineReviewListPojo);

        //分发待办
        List<TodoTaskPojo> list = new ArrayList<>();
        for (String assigneeId : firstNode.getAssignees()) {
            TodoTaskPojo todoTaskPojo = new TodoTaskPojo();
            todoTaskPojo.setDocumentNo(approvalId);
            todoTaskPojo.setProcessTitle(processTitle);
            todoTaskPojo.setCurrentNode(ApprovalOrderEnum.PROOFREAD.getDesc());
            todoTaskPojo.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees()));
            todoTaskPojo.setModelId(model.getId());
            todoTaskPojo.setVersionNumber(model.getVersionNumber());
            todoTaskPojo.setOwnerId(assigneeId);
            todoTaskPojo.setDataType(CurrentNodeEnum.DATAAPPROVAL.getDesc());
            todoTaskPojo.setModelName(model.getModelName());
            todoTaskPojo.setCreatedById(userId);
            todoTaskPojo.setCreatedBy(createBy);
            todoTaskPojo.setCreationDate(engineReviewListPojo.getCreationDate());
            todoTaskPojo.setIsDelete(0);
            list.add(todoTaskPojo);
        }
        bd.getBusinessDatabase().doBatchInsert(list);

        //创建审批发起
        InitiatedTaskPojo initiatedTaskPojo = new InitiatedTaskPojo();
        initiatedTaskPojo.setDocumentNo(approvalId);
        initiatedTaskPojo.setProcessTitle(processTitle);
        initiatedTaskPojo.setCurrentNode(ApprovalOrderEnum.PROOFREAD.getDesc());
        initiatedTaskPojo.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees()));
        initiatedTaskPojo.setCreatedById(userId);
        initiatedTaskPojo.setCreatedBy(createBy);
        initiatedTaskPojo.setDataType(CurrentNodeEnum.DATAAPPROVAL.getDesc());
        initiatedTaskPojo.setModelName(model.getModelName());
        initiatedTaskPojo.setCreationDate(engineReviewListPojo.getCreationDate());
        initiatedTaskPojo.setIsDelete(0);
        initiatedTaskPojo.setEnableReturn(1);
        bd.getBusinessDatabase().doInsert(initiatedTaskPojo);

        //将参数绑定到该机型审批流程中
        List<String> collected = paramList.stream().map(EngineParamDetailPojo::getId).collect(Collectors.toList());
        bd.getBusinessDatabase()
                .update("version_status", ParamValueVersionEnum.UNDER.getCode()) // 更新版本状态为审核中
                .update("approval_id", approvalId) // 关联审批ID
                .update("last_update_date", new Date()) // 更新最后修改日期为当前日期
                .in("id", collected)
                .doUpdate(EngineParamDetailPojo.class); // 执行更新操作

        boolean b = false;
        // 保存审批环节配置
        List<ApprovalConfigPojo> approvalConfigs = new ArrayList<>();
        for (ApprovalNodeDTO nodeDTO : approvalNodeRequest.getNodeList()) {
            if (ObjectUtils.isEmpty(nodeDTO.getAssignees())) {
                b = true;
                continue;
            }
            Integer nodeOrder = nodeDTO.getNodeOrder();
            if (b) {
                nodeOrder = nodeOrder - 1;
            }
            ApprovalConfigPojo config = new ApprovalConfigPojo();
            config.setApprovalId(approvalId);
            config.setNodeName(nodeDTO.getNodeName());
            config.setAssignees(String.join(",", nodeDTO.getAssignees()));
            config.setNodeOrder(nodeOrder);
            config.setCreatedBy(userId);
            config.setCreationDate(Timestamp.valueOf(LocalDateTime.now()));
            approvalConfigs.add(config);
            b = false;
        }
        bd.getBusinessDatabase().doBatchInsert(approvalConfigs);

        //记录审批提交操作
        bd.getBusinessDatabase().doInsert(
                new ParamApprovalRecordPojo(
                        approvalId,
                        "发起审批",
                        xdapDeptUsersService.selectUserByID(userId).getUsername(),
                        "发起审批",
                        Timestamp.valueOf(LocalDateTime.now()),
                        "提交流程",
                        firstNode.getNodeOrder(),
                        Timestamp.valueOf(LocalDateTime.now()),
                        1
                )
        );

        // 参数发起审批后，删除填写人的待办
        TodoTaskPojo todoTaskPojo = bd.getBusinessDatabase()
                .eq("owner_id", userId)
                .eq("model_id", model.getId())
                .eq("data_type", "数据维护")
                .eq("is_delete", 0)
                .doQueryFirst(TodoTaskPojo.class);
        if (todoTaskPojo != null) {
            // 修改待办和发起的任务状态
            bd.getBusinessDatabase()
                    .update("is_delete", 1)
                    .update("current_node", "已维护")
                    .update("last_update_date", new Date())
                    .eq("document_no", todoTaskPojo.getDocumentNo())
                    .doUpdate(TodoTaskPojo.class);

            //新增这个人的填写的已办和经办
            CompletedTaskPojo completedTaskPojo = new CompletedTaskPojo();
            BeanUtils.copyProperties(todoTaskPojo, completedTaskPojo);
            completedTaskPojo.setCurrentProcessor(null);
            completedTaskPojo.setId(UUID.randomUUID().toString().replace("-", ""));
            completedTaskPojo.setDocumentNo(todoTaskPojo.getDocumentNo());
            completedTaskPojo.setCreationDate(engineReviewListPojo.getCreationDate());
            completedTaskPojo.setIsDelete(0);
            completedTaskPojo.setCurrentNode("已维护");
            bd.getBusinessDatabase().doInsert(completedTaskPojo);

            InitiatedTaskPojo initiatedTask = new InitiatedTaskPojo();
            BeanUtils.copyProperties(todoTaskPojo, initiatedTask);
            initiatedTask.setCurrentProcessor(null);
            initiatedTask.setId(UUID.randomUUID().toString().replace("-", ""));
            initiatedTask.setDocumentNo(todoTaskPojo.getDocumentNo());
            initiatedTask.setCreationDate(engineReviewListPojo.getCreationDate());
            initiatedTask.setIsDelete(0);
            initiatedTask.setCurrentNode("已维护");
            bd.getBusinessDatabase().doInsert(initiatedTask);
        }
    }

    /**
     * 处理审批操作
     * 根据用户的审批操作（通过/拒绝）来推进审批流程，并更新相关数据状态
     *
     * @param handleApprovalDTO 审批处理请求对象
     * @return 审批结果描述
     */
    @Override
    @Transactional
    public String handleApproval(HandleApprovalDTO handleApprovalDTO) {
        String approvalId = handleApprovalDTO.getApprovalId();
        String approver = handleApprovalDTO.getUserId();

        // 验证流程状态和用户权限
        EngineReviewListPojo reviewListPojo = bd.getBusinessDatabase()
                .eq("id", approvalId)
                .doQueryFirst(EngineReviewListPojo.class);
        List<String> assigneeList = getStrings(reviewListPojo);
        if (!assigneeList.contains(approver)) {
            throw new CommonException("当前用户无权限处理此审批环节");
        }
        DataEntryEngineModelPojo model = bd.getBusinessDatabase()
                .eq("id", reviewListPojo.getModelId())
                .doQueryFirst(DataEntryEngineModelPojo.class);
        // 获取当前流程填写的人填写的参数
        List<EngineParamDetailPojo> list = bd.getBusinessDatabase()
                .eq("engine_model_id", model.getId())
                .eq("major_version", model.getVersionNumber())
                .eq("last_updated_by", reviewListPojo.getCreatedBy())
                .doQuery(EngineParamDetailPojo.class);

        ParamApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("approval_id", approvalId)
                .orderBy("operate_time", "desc")
                .doQueryFirst(ParamApprovalRecordPojo.class);
        ApprovalConfigPojo approvalConfigPojo = bd.getBusinessDatabase()
                .eq("approval_id", approvalId)
                .eq("node_name", reviewListPojo.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);
        if (!Objects.equals(reviewListPojo.getNodeName(), "会签")) {
            String lockKey = FLOW_LOCK_PREFIX + approvalId + ":" + reviewListPojo.getNodeName();
            String lockValue = UUID.randomUUID().toString();
            boolean lockAcquired = redisLockUtil
                    .tryLock(lockKey, lockValue, FLOW_LOCK_EXPIRE_SECONDS, TimeUnit.SECONDS);
            if (!lockAcquired) {
                throw new CommonException("当前节点正在处理，请稍后重试");
            }
            try {
                // 查询已完成的任务,检查当前节点是否完成
                int processedCount = bd.getBusinessDatabase()
                        .eq("approval_id", approvalId)
                        .eq("node_name", reviewListPojo.getNodeName())
                        .eq("approval_level", lastedRecord.getApprovalLevel())
                        .doQuery(ParamApprovalRecordPojo.class).size();
                if (processedCount > 0) {
                    throw new CommonException("此节点已被他人处理");
                }
                myself.processApproval(reviewListPojo, handleApprovalDTO, approvalConfigPojo, lastedRecord, list);
            } finally {
                redisLockUtil.unlock(lockKey, lockValue);
            }
        }
        // 会签节点
        else {
            myself.processApproval(reviewListPojo, handleApprovalDTO, approvalConfigPojo, lastedRecord, list);
        }
        return "已审批";
    }

    @Override
    public void processApproval(
            EngineReviewListPojo flow,
            HandleApprovalDTO request,
            ApprovalConfigPojo currentNode,
            ParamApprovalRecordPojo lastedRecord,
            List<EngineParamDetailPojo> list
    ) {
        // 新增当前审批结果
        bd.getBusinessDatabase().doInsert(new ParamApprovalRecordPojo(
                flow.getId(),
                currentNode.getNodeName(),
                request.getUserId(),
                request.getOperator(),
                Timestamp.valueOf(LocalDateTime.now()),
                request.getComment(),
                currentNode.getNodeOrder(),
                Timestamp.valueOf(LocalDateTime.now()),
                lastedRecord.getApprovalLevel()
        ));

        // 软删除当前节点当前处理人的待办
        if (!Objects.equals(currentNode.getNodeName(), "会签")) {
            // 抢签节点还需要软删除其他人的待办
            bd.getBusinessDatabase()
                    .eq("document_no", flow.getId())
                    .eq("current_node", currentNode.getNodeName())
                    .ne("owner_id", request.getUserId())
                    .update("is_delete", 1)
                    .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                    .doUpdate(TodoTaskPojo.class);
        }
        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .eq("current_node", currentNode.getNodeName())
                .eq("owner_id", request.getUserId())
                .update("is_delete", 1)
                .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                .doUpdate(TodoTaskPojo.class);

        // 新增当前处理人的已办
        CompletedTaskPojo completedTaskPojo = new CompletedTaskPojo();
        completedTaskPojo.setDocumentNo(flow.getId());
        completedTaskPojo.setCreatedById(request.getUserId());
        completedTaskPojo.setCreatedBy(xdapDeptUsersService.selectUserByID(request.getUserId()).getUsername());
        completedTaskPojo.setCurrentNode(currentNode.getNodeName());
        completedTaskPojo.setCurrentProcessor(JSON.toJSONString(currentNode.getAssignees().split(",")));
        completedTaskPojo.setDataType("数据审批");
        completedTaskPojo.setOwnerId(request.getUserId());
        completedTaskPojo.setProcessTitle(flow.getProcessTopic());
        completedTaskPojo.setCreationDate(flow.getCreationDate());
        completedTaskPojo.setIsDelete(0);
        completedTaskPojo.setModelId(flow.getModelId());
        bd.getBusinessDatabase().doInsert(completedTaskPojo);

        // 处理驳回逻辑
        if ("REJECT".equals(request.getOperator())) {
            myself.cancelProcess(
                    flow,
                    currentNode,
                    ParamValueVersionEnum.REFUSE,
                    request.getUserId()
            );
            return;
        }

        // 通过当前节点
        myself.processNextNode(
                flow,
                currentNode,
                request.getUserId(),
                list
        );
    }

    // 检查节点是否完成
    public boolean checkNodeComplete(EngineReviewListPojo flow, ApprovalConfigPojo node) {
        ParamApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .orderBy("operate_time", "desc")
                .doQueryFirst(ParamApprovalRecordPojo.class);
        Integer processedCount = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_name", node.getNodeName())
                .eq("approval_level", lastedRecord.getApprovalLevel())
                .doQuery(ParamApprovalRecordPojo.class).size();
        if ("会签".equals(node.getNodeName())) {
            return processedCount.equals(Arrays.asList(node.getAssignees().split(",")).size());
        } else {
            return processedCount >= 1;
        }
    }

    @Override
    public void cancelProcess(
            EngineReviewListPojo flow,
            ApprovalConfigPojo node,
            ParamValueVersionEnum status,
            String userId
    ) {
        //
        DataEntryEngineModelPojo model = bd.getBusinessDatabase()
                .eq("id", flow.getModelId())
                .doQueryFirst(DataEntryEngineModelPojo.class);
        // 删除所有待办
        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .eq("current_node", node.getNodeName())
                .update("is_delete", 1)
                .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                .doUpdate(TodoTaskPojo.class);
        // 更改参数状态为草稿
        bd.getBusinessDatabase()
                .update("version_status", ParamValueVersionEnum.DRAFT.getCode())
                .update("operation", "")// 清空操作状态
//                .update("minor_version", "")// 小版本清空
                .update("last_update_date", new Date())
                .eq("last_updated_by", flow.getCreatedBy()) // 流程创建人
                .eq("engine_model_id", flow.getModelId())
                .eq("major_version", model.getVersionNumber())
                .doUpdate(EngineParamDetailPojo.class);
        // 审批流改为已拒绝或已撤回
        bd.getBusinessDatabase()
                .update("status_code", status.getCode())
                .update("status_description", status.getDesc())
                .update("approver_persons", "")
                .update("last_update_date", new Date())
                .update("return_num", flow.getReturnNum() + 1)
                .update("pre_node", node.getNodeOrder())
                .update("node_name", "")
                .eq("id", flow.getId())
                .doUpdate(EngineReviewListPojo.class);
        // 生成拒绝提醒
        if (status.getCode() == 4) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(userId);
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(userId).getUsername());
            todoTask.setCurrentNode("编制");
            todoTask.setDataType("数据拒绝");
            todoTask.setDocumentNo(flow.getId());
            todoTask.setCreationDate(flow.getCreationDate());
            todoTask.setIsDelete(0);
            todoTask.setModelId(flow.getModelId());
            todoTask.setModelName(flow.getModelName());
            todoTask.setProcessTitle(flow.getProcessTopic());
            todoTask.setStatusCode(flow.getStatusDescription());
            todoTask.setVersionNumber(0);
            todoTask.setOwnerId(flow.getCreatedBy());
            todoTask.setCurrentProcessor(JSON.toJSONString(Collections.singletonList(flow.getCreatedBy())));
            bd.getBusinessDatabase().doInsert(todoTask);
        }
        // 更新发起和已办
        myself.updateTasks(flow, "编制", 0, node);
    }

    @Override
    public void updateTasks(
            EngineReviewListPojo flow,
            String status,
            Integer enableReturn,
            ApprovalConfigPojo currentNode
    ) {
        // 更新已发起的任务状态
        bd.getBusinessDatabase()
                .update("current_node", status)
                .update("last_update_date", new Date())
                .update("current_processor", currentNode == null ? "" : JSON.toJSONString(currentNode.getAssignees().split(",")))
                .eq("document_no", flow.getId())
                .update("enable_return", enableReturn)
                .doUpdate(InitiatedTaskPojo.class);
        // 更新已完成的任务状态
        bd.getBusinessDatabase()
                .update("current_node", status)
                .update("last_update_date", new Date())
                .update("current_processor", currentNode == null ? "" : JSON.toJSONString(currentNode.getAssignees().split(",")))
                .eq("document_no", flow.getId())
                .doUpdate(CompletedTaskPojo.class);
    }

    @Override
    public void processNextNode(
            EngineReviewListPojo flow,
            ApprovalConfigPojo currentNode,
            String userId,
            List<EngineParamDetailPojo> list
    ) {
        // 处理通过逻辑
        ApprovalConfigPojo approvalConfigPojo = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_order", currentNode.getNodeOrder() + 1)
                .doQueryFirst(ApprovalConfigPojo.class);

        // 检查当前节点已完成
        if (checkNodeComplete(flow, currentNode)) {
            // 更新待办
            if (approvalConfigPojo != null) {
                myself.addNodeTodo(
                        flow,
                        approvalConfigPojo,
                        userId,
                        0
                );
            } else {
                // 待办环节修改
                myself.updateTasks(flow, ParamValueVersionEnum.PASSED.getDesc(), 0, null);

                DataEntryEngineModelPojo model = bd.getBusinessDatabase()
                        .eq("id", flow.getModelId())
                        .doQueryFirst(DataEntryEngineModelPojo.class);
                // 检查当前参数是否为一版本，是则更新参数，否则新建版本。
                // 这个机型下所有参数都全部写入一版且版本加一  没有参与审批的参数时原来的值,参与审批的参数值要取小版本值作为大版本
                // 现版本需要填写的全部参数
                List<EngineParamDetailPojo> oldDetails = bd.getBusinessDatabase()
                        .eq("engine_model_id", flow.getModelId())
                        .eq("major_version", model.getVersionNumber())
                        .ne("is_distributed_res", 2)
                        .doQuery(EngineParamDetailPojo.class);
                // 本次审核通过审核的参数id
                List<String> ids = list.stream()
                        .map(EngineParamDetailPojo::getId)
                        .collect(Collectors.toList());
                // 现版本需要填写但未填写的参数
                List<EngineParamDetailPojo> emptyParameters = bd.getBusinessDatabase()
                        .eq("engine_model_id", flow.getModelId())
                        .eq("major_version", model.getVersionNumber())
                        .ne("is_distributed_res", 2)
                        .isNull("parameter_value")
                        .doQuery(EngineParamDetailPojo.class);
                List<EngineParamDetailPojo> toBePassed = new ArrayList<>();
                if (emptyParameters.size() == oldDetails.size()) {
                    for (EngineParamDetailPojo item : list) {
                        bd.getBusinessDatabase()
                                .eq("id", item.getId())
                                .update("parameter_value", item.getMinorVersion())
                                .update("minor_version", null)
                                .doUpdate(EngineParamDetailPojo.class);
                        toBePassed.add(item);
                    }
                } else {
                    // 更新机型版本
                    List<EngineParamDetailPojo> toInsert = new ArrayList<>();
                    List<EngineParamDetailPojo> allOldParams = bd.getBusinessDatabase()
                            .eq("engine_model_id", flow.getModelId())
                            .eq("major_version", model.getVersionNumber())
                            .doQuery(EngineParamDetailPojo.class);
                    model.setVersionNumber(model.getVersionNumber() + 1);
                    for (EngineParamDetailPojo oldDetail : allOldParams) {
                        EngineParamDetailPojo engineParamDetailPojo = new EngineParamDetailPojo();
                        BeanUtils.copyProperties(oldDetail, engineParamDetailPojo
                                , "id");
                        if (ids.contains(oldDetail.getId())) {
                            engineParamDetailPojo.setParameterValue(oldDetail.getMinorVersion());
                            engineParamDetailPojo.setMinorVersion(null);
                            toBePassed.add(engineParamDetailPojo);
                        }
                        engineParamDetailPojo.setMajorVersion(model.getVersionNumber());
                        // 添加到待插入列表
                        toInsert.add(engineParamDetailPojo);
                    }
                    // 新增新版本参数
                    bd.getBusinessDatabase().doBatchInsert(toInsert);

                    // 这个机型版本加一,
                    bd.getBusinessDatabase()
                            .update("version_number", model.getVersionNumber())
                            .eq("id", flow.getModelId())
                            .doUpdate(DataEntryEngineModelPojo.class);
                }

                // 这一批数据改成审核通过,
                List<String> toBePassedIds = new ArrayList<>();
                if (!toBePassed.isEmpty()) {
                    toBePassedIds.addAll(
                            toBePassed.stream()
                                    .map(EngineParamDetailPojo::getId)
                                    .collect(Collectors.toList())
                    );
                }
                bd.getBusinessDatabase()
                        .update("version_status", ParamValueVersionEnum.PASSED.getCode())
                        .update("last_update_date", new Date())
                        .update("last_updated_by", null)
                        .in("id", toBePassedIds)
                        .doUpdate(EngineParamDetailPojo.class);
                // 审批流改为已通过
                bd.getBusinessDatabase()
                        .update("status_code", ParamValueVersionEnum.PASSED.getCode())
                        .update("status_description", ParamValueVersionEnum.PASSED.getDesc())
                        .update("approver_persons", "")
                        .update("last_update_date", new Date())
                        .update("pre_node", -1)
                        .update("node_name", null)
                        .eq("id", flow.getId())
                        .doUpdate(EngineReviewListPojo.class);

                // 判断当前是否完成全部审批任务
                List<EngineParamDetailPojo> finishDetails = bd.getBusinessDatabase()
                        .eq("engine_model_id", flow.getModelId())
                        .eq("major_version", model.getVersionNumber())
                        .ne("is_distributed_res", 2)
                        .eq("version_status", ParamValueVersionEnum.PASSED.getCode())
                        .doQuery(EngineParamDetailPojo.class);
                // 机型已完成分发并且全部分发参数已完成填写并审核通过
                if (Objects.equals(model.getDistributeStatus(), DistributeStatusEnum.DISTRIBUTED.getCode())
                        && oldDetails.size() == finishDetails.size()) {
                    // 修改机型状态为已完成
                    bd.getBusinessDatabase()
                            .eq("id", model.getId())
                            .update("distribute_status", DistributeStatusEnum.COMPLETE.getCode())
                            .doUpdate(DataEntryEngineModelPojo.class);
                    // 修改新参数状态为草稿并清除所有责任人和填写人
                    List<String> collected = finishDetails.stream()
                            .map(EngineParamDetailPojo::getId)
                            .collect(Collectors.toList());
                    bd.getBusinessDatabase()
                            .update("is_distributed_res", 0)
                            .update("is_distributed_filled", 0)
                            .update("responsible_person_id", null)
                            .update("filled_by", null)
                            .update("minor_version", null)
                            .update("version_status", ParamValueVersionEnum.DRAFT.getCode())
                            .in("id", collected)
                            .doUpdate(EngineParamDetailPojo.class);
                }
            }
        }
    }

    @Override
    public void addNodeTodo(
            EngineReviewListPojo flow,
            ApprovalConfigPojo node,
            String createBy,
            Integer enableReturn
    ) {
        // 更新审批流到下个审批节点
        bd.getBusinessDatabase()
                .update("approver_persons", node.getAssignees())
                .update("node_name", node.getNodeName())
                .update("last_update_date", new Date())
                .update("pre_node", -1)
                .eq("id", flow.getId())
                .doUpdate(EngineReviewListPojo.class);
        // 为下个环节的人生成待办任务
        DataEntryEngineModelPojo modelPojo = dataEntryEngineModelService.selectBymodelId(flow.getModelId());
        for (String nextAssId : node.getAssignees().split(",")) {
            TodoTaskPojo todoTaskPojo = new TodoTaskPojo();
            todoTaskPojo.setDocumentNo(flow.getId());
            todoTaskPojo.setProcessTitle(flow.getProcessTopic());
            todoTaskPojo.setCurrentNode(node.getNodeName());
            todoTaskPojo.setCurrentProcessor(JSON.toJSONString(Arrays.asList(node.getAssignees().split(","))));
            todoTaskPojo.setModelId(flow.getModelId());
            todoTaskPojo.setVersionNumber(modelPojo.getVersionNumber());
            todoTaskPojo.setOwnerId(nextAssId);
            todoTaskPojo.setDataType(CurrentNodeEnum.DATAAPPROVAL.getDesc());
            todoTaskPojo.setModelName(modelPojo.getModelName());
            todoTaskPojo.setCreatedById(createBy);
            todoTaskPojo.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername());
            todoTaskPojo.setCreationDate(flow.getCreationDate());
            todoTaskPojo.setIsDelete(0);
            bd.getBusinessDatabase().doInsert(todoTaskPojo);
        }
        myself.updateTasks(flow, node.getNodeName(), enableReturn, node);
    }

    /**
     * 更新流程标题
     * 更新审批流程的标题信息，同时更新相关的待办、已办和发起任务的标题
     *
     * @param flowId 流程ID
     * @param title  新的流程标题
     */
    @Override
    @Transactional
    public void updateFlowTitle(String flowId, String title) {
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .ne("status_code", ParamValueVersionEnum.PASSED.getCode())
                .doQueryFirst(EngineReviewListPojo.class);

        if (flow == null) {
            throw new CommonException("流程不存在");
        }

        if (Objects.equals(title, flow.getProcessTopic())) {
            return;
        }

        bd.getBusinessDatabase()
                .eq("id", flowId)
                .update("process_topic", title)
                .doUpdate(EngineReviewListPojo.class);

        bd.getBusinessDatabase()
                .eq("document_no", flowId)
                .update("process_title", title)
                .doUpdate(TodoTaskPojo.class);
        bd.getBusinessDatabase()
                .eq("document_no", flowId)
                .update("process_title", title)
                .doUpdate(CompletedTaskPojo.class);
        bd.getBusinessDatabase()
                .eq("document_no", flowId)
                .update("process_title", title)
                .doUpdate(InitiatedTaskPojo.class);
    }

    /**
     * 继续审批流程
     * 重新发起审批流程，清除原流程节点的所有待办任务并重新分配
     *
     * @param flowId 流程ID
     * @param userId 用户ID
     */
    @Override
    public void continueApproval(String flowId, String userId) {
        EngineReviewListPojo reviewListPojo = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(EngineReviewListPojo.class);
        if (reviewListPojo == null) {
            throw new CommonException("流程不存在");
        }

        // 清除原流程节点的所有待办
        bd.getBusinessDatabase()
                .eq("document_no", reviewListPojo.getId())
                .update("is_delete", 1)
                .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                .doUpdate(TodoTaskPojo.class);

        // 修改非进行中的流程为进行中
        ApprovalConfigPojo firstNode = bd.getBusinessDatabase()
                .eq("approval_id", reviewListPojo.getId())
                .orderBy("node_order", "asc")
                .doQueryFirst(ApprovalConfigPojo.class);
        if (!Objects.equals(reviewListPojo.getStatusCode(), ParamValueVersionEnum.UNDER.getCode())) {
            reviewListPojo.setPreNode(-1);
            reviewListPojo.setStatusCode(ParamValueVersionEnum.UNDER.getCode());
            reviewListPojo.setNodeName(firstNode.getNodeName());

            // 这一批数据改成审核中
            bd.getBusinessDatabase()
                    .update("version_status", ParamValueVersionEnum.UNDER.getCode())
                    .update("last_update_date", new Date())
                    .eq("approval_id", reviewListPojo.getId())
                    .doUpdate(EngineParamDetailPojo.class);
            // 审批流改为审核中
            bd.getBusinessDatabase()
                    .update("status_code", ParamValueVersionEnum.UNDER.getCode())
                    .update("status_description", ParamValueVersionEnum.UNDER.getDesc())
                    .update("last_update_date", new Date())
                    .eq("id", reviewListPojo.getId())
                    .doUpdate(EngineReviewListPojo.class);
        }

        // 添加新待办
        myself.addNodeTodo(
                reviewListPojo,
                firstNode,
                userId,
                1
        );

        ParamApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("approval_id", reviewListPojo.getId())
                .orderBy("operate_time", "desc")
                .doQueryFirst(ParamApprovalRecordPojo.class);
        bd.getBusinessDatabase().doInsert(
                new ParamApprovalRecordPojo(
                        reviewListPojo.getId(),
                        "重新发起",
                        xdapDeptUsersService.selectUserByID(userId).getUsername(),
                        "重新发起",
                        Timestamp.valueOf(LocalDateTime.now()),
                        "MSG",
                        firstNode.getNodeOrder(),
                        Timestamp.valueOf(LocalDateTime.now()),
                        lastedRecord.getApprovalLevel() + 1
                )
        );
    }

    /**
     * 获取可编辑节点
     * 获取指定流程中可编辑的审批节点列表
     *
     * @param flowId 流程ID
     * @return 可编辑节点列表
     */
    @Override
    public List<String> getEditableNodes(String flowId) {
        return Collections.emptyList();
    }

    /**
     * 更新节点配置
     * 更新审批流程中的节点配置信息
     *
     * @param form 更新节点表单对象
     */
    @Override
    public void updateNode(UpdateNodeForm form) {
        // 检查流程
        EngineReviewListPojo reviewListPojo = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .ne("status_code", ParamValueVersionEnum.PASSED.getCode())
                .doQueryFirst(EngineReviewListPojo.class);

        if (reviewListPojo == null) {
            throw new CommonException("流程不存在");
        }

        // 获取可更新流程节点名称
        List<ApprovalConfigPojo> nodes = bd.getBusinessDatabase()
                .eq("approval_id", form.getFlowId())
                .doQuery(ApprovalConfigPojo.class);

        // 将节点列表转换为 Map，方便后续查找
        Map<String, ApprovalConfigPojo> currentNodeMap = nodes.stream()
                .collect(Collectors.toMap(
                        ApprovalConfigPojo::getNodeName,
                        node -> node,
                        (oldValue, newValue) -> oldValue
                ));
        Map<String, ApprovalNodeDTO> newNodeMap = form.getNodeList().stream()
                .collect(Collectors.toMap(
                        ApprovalNodeDTO::getNodeName,
                        node -> node,
                        (oldValue, newValue) -> oldValue
                ));

        // 更新节点前，先删除待办
        bd.getBusinessDatabase()
                .eq("document_no", form.getFlowId())
                .eq("is_delete", 0)
                .update("is_delete", 1)
                .doUpdate(TodoTaskPojo.class);

        boolean addNode = false;
        int orderOffset = 0;
        List<ApprovalNodeDTO> sorted = form.getNodeList().stream()
                .sorted(Comparator.comparing(ApprovalNodeDTO::getNodeOrder))
                .collect(Collectors.toList());

        // 更新可选的会签节点
        ApprovalConfigPojo signNode = currentNodeMap.get("会签");
        ApprovalNodeDTO newSignNode = newNodeMap.get("会签");
        if (newSignNode != null) {
            // 新增节点
            if (!newSignNode.getAssignees().isEmpty() && signNode == null) {
                // 找到新增节点的插入位置
                int insertOrder = newSignNode.getNodeOrder();
                // 新增会签节点
                ApprovalConfigPojo addNewNode = new ApprovalConfigPojo();
                addNewNode.setApprovalId(form.getFlowId());
                addNewNode.setNodeName(newSignNode.getNodeName());
                addNewNode.setNodeOrder(insertOrder);
                addNewNode.setAssignees(String.join(",", newSignNode.getAssignees()));
                bd.getBusinessDatabase().doInsert(addNewNode);
                // 新增节点后，后续节点序号需要+1
                orderOffset = 1;
                addNode = true;
            }
            // 删除节点
            else if (newSignNode.getAssignees().isEmpty() && signNode != null) {
                // 删除会签节点
                bd.getBusinessDatabase()
                        .eq("id", signNode.getId())
                        .doDelete(ApprovalConfigPojo.class);
                // 删除节点后，后续节点序号需要-1
                orderOffset = -1;
                addNode = true;
            }
        }

        // 遍历所有节点，更新序号和处理人信息
        for (ApprovalNodeDTO newNode : sorted) {
            // 获取当前节点
            ApprovalConfigPojo node = currentNodeMap.get(newNode.getNodeName());
            if (node == null) {
                continue;
            }

            // 计算新序号：原始序号 + 偏移量
            int finalOrder = node.getNodeOrder() + orderOffset;
            // 更新节点信息
            if (addNode) {
                bd.getBusinessDatabase()
                        .eq("id", node.getId())
                        .update("node_order", finalOrder)
                        .update("assignees", String.join(",", newNode.getAssignees()))
                        .doUpdate(ApprovalConfigPojo.class);
            } else {
                // 无节点增减时，只更新处理人
                bd.getBusinessDatabase()
                        .eq("id", node.getId())
                        .update("assignees", String.join(",", newNode.getAssignees()))
                        .doUpdate(ApprovalConfigPojo.class);
            }
        }

        // 更新流程状态
        if (!Objects.equals(reviewListPojo.getProcessTopic(), form.getTitle())) {
            bd.getBusinessDatabase()
                    .eq("id", reviewListPojo.getId())
                    .update("process_topic", form.getTitle())
                    .doUpdate(EngineReviewListPojo.class);
        }
    }

    /**
     * 判断是否为直送流程
     * 检查指定流程是否为直送流程
     *
     * @param flowId 流程ID
     * @return 是否为直送流程
     */
    @Override
    public boolean getIsDirect(String flowId) {
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(EngineReviewListPojo.class);

        if (flow == null) {
            return false;
        }

        return flow.getPreNode() != -1;
    }

    /**
     * 获取审批用户节点
     * 获取指定流程的审批节点及其相关用户信息
     *
     * @param flowId 流程ID
     * @return 审批用户节点DTO
     */
    @Override
    public ApprovalNodesDTO getApprovalUsers(String flowId) {
        ApprovalNodesDTO nodes = new ApprovalNodesDTO();
        nodes.setProcessTitle("");
        nodes.setExplanation("");
        List<ApprovalUserNodeDTO> list = new ArrayList<>();

        // 获取到模板最近一次未完成的流程
        EngineReviewListPojo engineReviewList = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(EngineReviewListPojo.class);
        if (engineReviewList == null) {
            nodes.setNodeList(list);
            return nodes;
        }

        // 获取流程节点
        List<ApprovalConfigPojo> approvalConfigs = bd.getBusinessDatabase()
                .eq("approval_id", engineReviewList.getId())
                .doQuery(ApprovalConfigPojo.class);

        approvalConfigs.forEach(node -> {
            ApprovalUserNodeDTO dto = new ApprovalUserNodeDTO();
            List<String> userIds = Arrays.asList(node.getAssignees().split(","));
            dto.setNodeName(node.getNodeName());
            dto.setNodeOrder(node.getNodeOrder());
            dto.setAssignees(
                    bd.getSystemDatabase()
                            .in("id", userIds)
                            .doQuery(XdapUsers.class)
            );
            list.add(dto);
        });
        nodes.setProcessTitle(engineReviewList.getProcessTopic());
        nodes.setExplanation(engineReviewList.getReviewComment());
        nodes.setNodeList(list);
        return nodes;
    }

    /**
     * 直送审批到指定节点
     * 将审批流程直接发送到指定节点，跳过中间节点
     *
     * @param flowId 流程ID
     * @param userId 用户ID
     */
    @Override
    public void directSendingApproval(String flowId, String userId) {
        // 获取当前流程审批的参数
        List<EngineParamDetailPojo> engineParamDetails = bd.getBusinessDatabase()
                .eq("approval_id", flowId) // 关联审批ID
                .doQuery(EngineParamDetailPojo.class);
        if (engineParamDetails.isEmpty()) {
            throw new CommonException("流程无关联参数");
        }

        // 获取到未完成的流程
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .ne("pre_node", -1)
                .doQueryFirst(EngineReviewListPojo.class);
        if (flow == null) {
            throw new CommonException("流程没有直送节点");
        }

        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_name", flow.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);

        // 删除当前节点待办
        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .eq("current_node", currentNode.getNodeName())
                .update("is_delete", 1)
                .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                .doUpdate(TodoTaskPojo.class);

        // 根据状态不同获取节点和节点层级
        ApprovalConfigPojo preNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_order", flow.getPreNode())
                .doQueryFirst(ApprovalConfigPojo.class);
        ParamApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .orderBy("operate_time", "desc")
                .doQueryFirst(ParamApprovalRecordPojo.class) ;
        Integer level = Objects.equals(lastedRecord.getOperator(), "MSG") ? lastedRecord.getApprovalLevel() : lastedRecord.getApprovalLevel() + 1;

        // 重新创建待办继续流程
        myself.addNodeTodo(
                flow,
                preNode,
                userId,
                1
        );

        // 这一批数据改成审核中
        bd.getBusinessDatabase()
                .update("version_status", ParamValueVersionEnum.UNDER.getCode())
                .update("last_update_date", new Date())
                .eq("approval_id", flow.getId())
                .doUpdate(EngineParamDetailPojo.class);
        // 审批流改为审核中
        bd.getBusinessDatabase()
                .update("status_code", ParamValueVersionEnum.UNDER.getCode())
                .update("status_description", ParamValueVersionEnum.UNDER.getDesc())
                .update("node_name", preNode.getNodeName())
                .update("approver_persons", preNode.getAssignees())
                .update("last_update_date", new Date())
                .eq("id", flow.getId()).doUpdate(EngineReviewListPojo.class);

        // 清除拒绝提醒待办
        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .eq("data_type", "数据拒绝")
                .update("is_delete", 1)
                .doUpdate(TodoTaskPojo.class);

        // 创建直送记录
        bd.getBusinessDatabase().doInsert(
                new ParamApprovalRecordPojo(
                        flow.getId(),
                        "直送至" + preNode.getNodeName(),
                        xdapDeptUsersService.selectUserByID(userId).getUsername(),
                        "MSG",
                        Timestamp.valueOf(LocalDateTime.now()),
                        "直送",
                        currentNode.getNodeOrder(),
                        Timestamp.valueOf(LocalDateTime.now()),
                        level
                )
        );
    }

    /**
     * 获取退回节点列表
     * 获取可以退回的审批节点列表
     *
     * @param flowId 流程ID
     * @return 退回节点列表
     */
    @Override
    public List<String> getReturnNodes(String flowId) {
        String userId = runtimeAppContextService.getCurrentUserId();
        
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(EngineReviewListPojo.class);
        
        if (flow == null) {
            throw new CommonException("流程不存在");
        }
        
        boolean isParticipant = isFlowParticipant(flow, userId);
        if (!isParticipant) {
            throw new CommonException("无权限查看退回节点");
        }
        
        ApprovalConfigPojo approvalConfigPojo = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_name", flow.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);
        
        if (approvalConfigPojo == null) {
            throw new CommonException("当前节点配置不存在");
        }
        
        return bd.getBusinessDatabase()
                .eq("approval_id", flowId)
                .lt("node_order", approvalConfigPojo.getNodeOrder())
                .doQuery(ApprovalConfigPojo.class)
                .stream().sorted(Comparator.comparingInt(ApprovalConfigPojo::getNodeOrder))
                .collect(Collectors.toList())
                .stream().map(ApprovalConfigPojo::getNodeName)
                .collect(Collectors.toList());
    }

    /**
     * 处理退回至指定节点
     * 将审批流程退回至指定节点
     *
     * @param form 退回节点表单
     */
    @Override
    public void handleReturnToNode(HandleReturnNodeForm form) {
        // 查找流程
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .doQueryFirst(EngineReviewListPojo.class);
        if (flow ==  null) {
            throw new CommonException("流程不存在");
        }

        // 查找当前节点
        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_name", flow.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);

        if (!Arrays.asList(currentNode.getAssignees().split(",")).contains(form.getProcessUserId())) {
            throw new CommonException("无权限操作");
        }

        String lockKey = FLOW_LOCK_PREFIX + flow.getId() + ":" + currentNode.getNodeName();
        String lockValue = UUID.randomUUID().toString();
        boolean lockAcquired = redisLockUtil
                .tryLock(lockKey, lockValue, FLOW_LOCK_EXPIRE_SECONDS, TimeUnit.SECONDS);
        if (!lockAcquired) {
            throw new CommonException("当前节点正在处理，请稍后重试");
        }
        try {
            // 删除当前节点待办
            bd.getBusinessDatabase()
                    .eq("document_no", flow.getId())
                    .eq("current_node", currentNode.getNodeName())
                    .update("is_delete", 1)
                    .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                    .doUpdate(TodoTaskPojo.class);

            // 更新流程节点
            ApprovalConfigPojo toNode = bd.getBusinessDatabase()
                    .eq("approval_id", form.getFlowId())
                    .eq("node_name", form.getNodeName())
                    .doQueryFirst(ApprovalConfigPojo.class);
            if (toNode == null) {
                throw new CommonException("找不到目标节点");
            }

            bd.getBusinessDatabase()
                    .eq("id", flow.getId())
                    .update("current_node", toNode.getNodeOrder())
                    .update("pre_node", currentNode.getNodeOrder())
                    .doUpdate(ApprovalFlowPojo.class);

            // 生成新的待办
            myself.addNodeTodo(flow, toNode, form.getCreateUserId(), 0);

            // 生成处理记录
            ParamApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                    .eq("approval_id", flow.getId())
                    .orderBy("operate_time", "desc")
                    .doQueryFirst(ParamApprovalRecordPojo.class);
            bd.getBusinessDatabase().doInsert(
                    new ParamApprovalRecordPojo(
                            flow.getId(),
                            currentNode.getNodeName(),
                            form.getProcessUserId(),
                            "RETURN",
                            Timestamp.valueOf(LocalDateTime.now()),
                            "退回",
                            currentNode.getNodeOrder(),
                            Timestamp.valueOf(LocalDateTime.now()),
                            lastedRecord.getApprovalLevel()
                    )
            );
            ParamApprovalRecordPojo approvalRecord = new ParamApprovalRecordPojo(
                    flow.getId(),
                    "退回至" + toNode.getNodeName(),
                    xdapDeptUsersService.selectUserByID(form.getProcessUserId()).getUsername(),
                    "MSG",
                    Timestamp.valueOf(LocalDateTime.now().plusSeconds(1)),
                    "退回",
                    currentNode.getNodeOrder(),
                    Timestamp.valueOf(LocalDateTime.now().plusSeconds(1)),
                    lastedRecord.getApprovalLevel() + 1
            );
            bd.getBusinessDatabase().doInsert(approvalRecord);
        } finally {
            redisLockUtil.unlock(lockKey, lockValue);
        }
    }

    @Override
    public void handleReturn(HandleApprovalRequest request) {
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", request.getFlowId())
                .doQueryFirst(EngineReviewListPojo.class);
        if (!Objects.equals(flow.getCreatedBy(), request.getUserId())) {
            throw new CommonException("不是申请人无法撤回");
        }
        if (!Objects.equals(flow.getStatusCode(), ParamValueVersionEnum.UNDER.getCode())) {
            throw new CommonException("不在流程无法撤回");
        }
        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", request.getFlowId())
                .eq("node_name", flow.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);

        String lockKey = FLOW_LOCK_PREFIX + flow.getId() + ":" + currentNode.getNodeName();
        String lockValue = UUID.randomUUID().toString();
        boolean lockAcquired = redisLockUtil
                .tryLock(lockKey, lockValue, FLOW_LOCK_EXPIRE_SECONDS, TimeUnit.SECONDS);
        if (!lockAcquired) {
            throw new CommonException("当前节点正在处理，请稍后重试");
        }
        try {
            if ("RETURN".equals(request.getResult())) {
                ParamApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                        .eq("approval_id", flow.getId())
                        .orderBy("operate_time", "desc")
                        .doQueryFirst(ParamApprovalRecordPojo.class);

                ParamApprovalRecordPojo approvalRecord = new ParamApprovalRecordPojo(
                        flow.getId(),
                        "已撤回",
                        xdapDeptUsersService.selectUserByID(request.getUserId()).getUsername(),
                        "MSG",
                        Timestamp.valueOf(LocalDateTime.now()),
                        "撤回",
                        currentNode.getNodeOrder(),
                        Timestamp.valueOf(LocalDateTime.now()),
                        lastedRecord.getApprovalLevel() + 1
                );
                bd.getBusinessDatabase().doInsert(approvalRecord);

                // 申请人撤回
                myself.cancelProcess(flow, currentNode, ParamValueVersionEnum.WITHDRAWN, request.getUserId());
            } else {
                throw new CommonException("无法撤回");
            }
        } finally {
            redisLockUtil.unlock(lockKey, lockValue);
        }
    }


    /**
     * 查看审批详情
     * 根据审批ID获取审批过程中的数据和审批记录，供用户查看审批进度
     *
     * @param showActivitiDTO 显示审批请求对象
     * @return 包含审批数据和审批记录的DTO
     */
    @Override
    public ActivitiDataAndRecordDTO showActivitiData(ShowActivitiDTO showActivitiDTO) {
        EngineReviewListPojo engineFlow = bd.getBusinessDatabase()
                .eq("id", showActivitiDTO.getApprovalId() == null ? "" : showActivitiDTO.getApprovalId())
                .doQueryFirst(EngineReviewListPojo.class);
        if (engineFlow == null || showActivitiDTO.getApprovalId() == null) {
            throw new CommonException("无效的审批记录");
        }
        
        // 验证用户是否是流程参与人
        String userId = showActivitiDTO.getUserID();
        if (userId != null && !userId.isEmpty()) {
            boolean isParticipant = isFlowParticipant(engineFlow, userId);
            if (!isParticipant) {
                throw new CommonException("您不是该流程的参与人，无权查看");
            }
        }
        
        String approvalId = engineFlow.getId();
        ActivitiDataAndRecordDTO activitiDataAndRecordDTO = new ActivitiDataAndRecordDTO();
        // 获取机型
        DataEntryEngineModelPojo model = bd.getBusinessDatabase()
                .eq("id", engineFlow.getModelId())
                .doQueryFirst(DataEntryEngineModelPojo.class);
        activitiDataAndRecordDTO.setModel(model);
        //查找审批数据
        List<ActivitiDataDTO> activitiDataDTOS = new ArrayList<>();

        //通过审批ID找到审批中的参数 通过参数ID匹配参数变动说明
        List<EngineParamDetailPojo> detailPojos = bd.getBusinessDatabase()
                .eq("approval_id", approvalId)
                .doQuery(EngineParamDetailPojo.class);
        Set<String> ids = detailPojos.stream().map(EngineParamDetailPojo::getId).collect(Collectors.toSet());
        if (ObjectUtils.isEmpty(ids)) {
            throw new CommonException("该审批流没有绑定的参数，请维护好参数后重新发起审批");
        }
        // 查询数据变更评论
        List<DataChangeCommentPojo> dataChangeCommentPojos = bd.getBusinessDatabase()
                .viewQueryMode(true)
                .view("selectLastedComment")
                .setVar("paramIds", ids)
                .doQuery(DataChangeCommentPojo.class);
        for (DataChangeCommentPojo dataChangeCommentPojo : dataChangeCommentPojos) {
            ActivitiDataDTO activitiDataDTO = new ActivitiDataDTO();
            DataEntryEngineModelPojo modelPojo = dataEntryEngineModelService.selectBymodelId(dataChangeCommentPojo.getEngineModelId());
            BeanUtils.copyProperties(dataChangeCommentPojo, activitiDataDTO);
            activitiDataDTO.setEngineModelName(modelPojo.getModelName());
            activitiDataDTO.setChangeComment(dataChangeCommentPojo.getChangeComment());
            activitiDataDTOS.add(activitiDataDTO);
        }
        activitiDataAndRecordDTO.setActivitiDataDTOS(sortValueChange(activitiDataDTOS));
        List<FlowNode> flowNodes = new ArrayList<>();
        EngineReviewListPojo flow = bd.getBusinessDatabase()
                .eq("id", approvalId)
                .doQueryFirst(EngineReviewListPojo.class);
        if (flow == null) {
            activitiDataAndRecordDTO.setFlowNodes(flowNodes);
            return activitiDataAndRecordDTO;
        }
        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", approvalId)
                .eq("node_name", flow.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);
        // 查询所有流程记录
        List<ParamApprovalRecordPojo> allRecord = bd.getBusinessDatabase()
                .eq("approval_id", approvalId)
                .orderBy("operate_time", "desc")
                .doQuery(ParamApprovalRecordPojo.class);
        //获取配置
        List<ApprovalConfigPojo> nodes = bd.getBusinessDatabase()
                .eq("approval_id", approvalId)
                .doQuery(ApprovalConfigPojo.class);
        Map<String, ApprovalConfigPojo> nodesMap = nodes.stream()
                .filter(config -> config.getNodeName() != null)
                .collect(Collectors.toMap(
                        ApprovalConfigPojo::getNodeName,
                        config -> config,
                        (existing, replacement) -> existing  // 如果有重复键，保留第一个
                ));

        // 获取所有层级
        Map<Integer, List<ParamApprovalRecordPojo>> levelMap = allRecord.stream()
                .collect(Collectors.groupingBy(
                        ParamApprovalRecordPojo::getApprovalLevel,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> list.stream()
                                        .sorted(Comparator.comparing(ParamApprovalRecordPojo::getApprovalLevel))
                                        .collect(Collectors.toList())
                        )
                ));

        // 获取最大层级
        int maxLevel = levelMap.keySet().stream().max(Integer::compare).orElse(1);
        for (Map.Entry<Integer, List<ParamApprovalRecordPojo>> entry : levelMap.entrySet()) {
            // 获取到每一层
            int level = entry.getKey();
            Set<Integer> nodeList = new HashSet<>();
            List<ParamApprovalRecordPojo> records = entry.getValue();
            List<ParamApprovalRecordPojo> uniqueRecords = new ArrayList<>(records.stream()
                    .collect(Collectors.toMap(
                            ParamApprovalRecordPojo::getNodeName,
                            Function.identity(),
                            (first, second) -> first
                    ))
                    .values());
            uniqueRecords.forEach(approvalRecord -> {
                ApprovalConfigPojo approvalConfigPojo = nodesMap.get(approvalRecord.getNodeName());
                if (approvalConfigPojo != null) {
                    flowNodes.add(getFlowNodeView(approvalConfigPojo, approvalId, level));
                    nodeList.add(approvalConfigPojo.getNodeOrder());
                } else {
                    FlowNode flowNode = new FlowNode();
                    flowNode.setNode(approvalRecord.getNodeName());
                    flowNode.setTodoUserName(approvalRecord.getAssignee());
                    flowNode.setResult(approvalRecord.getOperator());
                    flowNode.setApprovalTime(new Timestamp(approvalRecord.getOperateTime().getTime()));
                    flowNodes.add(flowNode);
                }
            });

            if (level == maxLevel && Objects.equals(flow.getStatusCode(), ParamValueVersionEnum.UNDER.getCode()) ) {
                // 最后一层，添加待处理信息
                nodes.forEach(node -> {
                    if (!nodeList.contains(node.getNodeOrder()) && node.getNodeOrder() >= currentNode.getNodeOrder()) {
                        flowNodes.add(getFlowNodeView(node, approvalId, maxLevel));
                    }
                });
            }
        }

        // 查询基础数据
        activitiDataAndRecordDTO.setCurrentNode(flow.getNodeName() == null ? "无" : flow.getNodeName());
        activitiDataAndRecordDTO.setCreateBy(
                getUserNames(
                        Arrays.asList(flow.getApplicant().split(","))
                )
        );
        activitiDataAndRecordDTO.setCreateTime(flow.getCreationDate());
        activitiDataAndRecordDTO.setProcessor(
                !Objects.equals(flow.getStatusCode(), ParamValueVersionEnum.PASSED.getCode()) ?
                        getUserNames(
                                Arrays.asList(currentNode.getAssignees().split(","))
                        ) : "无"
        );
        activitiDataAndRecordDTO.setModelName(flow.getModelName());
        activitiDataAndRecordDTO.setApprovalStatus(flow.getStatusDescription());
        activitiDataAndRecordDTO.setProcessTitle(flow.getProcessTopic());
        List<FlowNode> sortedNode = flowNodes.stream()
                .sorted(Comparator.comparing(FlowNode::getApprovalTime,
                                Comparator.nullsLast(Comparator.naturalOrder()))
                        .thenComparing(FlowNode::getNodeOrder))
                .collect(Collectors.toList());
        activitiDataAndRecordDTO.setFlowNodes(sortedNode);

        return activitiDataAndRecordDTO;
    }
    
    /**
     * 验证用户是否是流程参与人
     * 参与人包括：发起人、当前审批人、已审批过的人
     *
     * @param flow 流程对象
     * @param userId 用户ID
     * @return 是否是参与人
     */
    private boolean isFlowParticipant(EngineReviewListPojo flow, String userId) {
        // 1. 检查是否是发起人
        if (userId.equals(flow.getCreatedBy())) {
            return true;
        }
        
        // 2. 检查是否是申请人（可能是多人，用逗号分隔）
        if (flow.getApplicant() != null) {
            List<String> applicants = Arrays.asList(flow.getApplicant().split(","));
            if (applicants.contains(userId)) {
                return true;
            }
        }
        
        // 3. 检查是否是当前审批人
        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_name", flow.getNodeName())
                .doQueryFirst(ApprovalConfigPojo.class);
        
        if (currentNode != null && currentNode.getAssignees() != null) {
            List<String> assignees = Arrays.asList(currentNode.getAssignees().split(","));
            if (assignees.contains(userId)) {
                return true;
            }
        }
        
        // 4. 检查是否已审批过
        List<ParamApprovalRecordPojo> records = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("operator_id", userId)
                .doQuery(ParamApprovalRecordPojo.class);
        
        if (!records.isEmpty()) {
            return true;
        }
        
        return false;
    }

    private FlowNode getFlowNodeView(
            ApprovalConfigPojo node,
            String flowId,
            int level
    ) {
        FlowNode nodeView = new FlowNode();
        if (Objects.equals(node.getNodeName(), "会签")) {
            List<ParamApprovalRecordPojo> records = bd.getBusinessDatabase()
                    .eq("approval_id", flowId)
                    .eq("node_name", node.getNodeName())
                    .eq("approval_level", level)
                    .doQuery(ParamApprovalRecordPojo.class);
            List<String> results = records.stream()
                    .map(ParamApprovalRecordPojo::getOperator).collect(Collectors.toList());
            List<ParamApprovalRecordPojo> reversedTime = records.stream().sorted(Comparator
                    .comparing(ParamApprovalRecordPojo::getOperateTime).reversed()).collect(Collectors.toList());
            if (records.size() == Arrays.asList(node.getAssignees().split(",")).size() || results.contains("REJECT") || results.contains("RETURN")) {
                // 节点已完成
                nodeView.setNodeOrder(node.getNodeOrder());
                String r = results.contains("RETURN") ? "RETURN" : "PASS";
                if (results.contains("REJECT")) {
                    r = "REJECT";
                }
                nodeView.setResult(r);
                nodeView.setNode(node.getNodeName());
                nodeView.setUndoUserName(getUserNames(Arrays.asList(node.getAssignees().split(","))));
                nodeView.setTodoUserName(getUserNames(Arrays.asList(node.getAssignees().split(","))));
                nodeView.setApprovalTime(new Timestamp(reversedTime.get(0).getOperateTime().getTime()));
                nodeView.setOpinions(records.stream().map(approvalRecord ->
                        getUserNames(Collections.singletonList(approvalRecord.getAssignee())) + ":" + approvalRecord.getApprovalComment()).collect(Collectors.toList()));
            } else {
                // 节点未完成
                nodeView.setNodeOrder(node.getNodeOrder());
                nodeView.setNode(node.getNodeName());
                nodeView.setResult("待审批");
                List<String> includedIds = records.stream().map(ParamApprovalRecordPojo::getCreatedBy).collect(Collectors.toList());
                nodeView.setTodoUserName(getUserNames(includedIds));
                nodeView.setUndoUserName(getUserNames(Arrays.asList(node.getAssignees().split(","))));
            }
        } else {
            ParamApprovalRecordPojo approvalRecord = bd.getBusinessDatabase()
                    .eq("approval_id", flowId)
                    .eq("node_name", node.getNodeName())
                    .eq("approval_level", level)
                    .doQueryFirst(ParamApprovalRecordPojo.class);
            nodeView.setNodeOrder(node.getNodeOrder());
            nodeView.setNode(node.getNodeName());
            if (approvalRecord != null) {
                // 节点已完成
                nodeView.setResult(approvalRecord.getOperator());
                nodeView.setOpinions(Collections.singletonList(getUserNames(Collections.singletonList(approvalRecord.getAssignee())) + ":" + approvalRecord.getApprovalComment()));
                nodeView.setApprovalTime(new Timestamp(approvalRecord.getOperateTime().getTime()));
                nodeView.setTodoUserName(getUserNames(Collections.singletonList(approvalRecord.getAssignee())));
            } else {
                // 节点未完成
                nodeView.setResult("待审批");
                nodeView.setTodoUserName("");
            }
            nodeView.setUndoUserName(getUserNames(Arrays.asList(node.getAssignees().split(","))));
        }
        return nodeView;
    }

    private String getUserNames(List<String> userIds) {
        StringJoiner joiner = new StringJoiner(" ");
        for (String userId : userIds) {
            XdapUsers user = bd.getSystemDatabase()
                    .eq("id", userId)
                    .doQueryFirst(XdapUsers.class);
            if (user != null) {
                joiner.add(user.getUsername());
            } else {
                // 处理空值情况
                joiner.add(userId);
            }
        }
        return joiner.toString();
    }

    private List<ActivitiDataDTO> sortValueChange(List<ActivitiDataDTO> changeList) {
        Collator collator = Collator.getInstance(Locale.CHINA);
        Comparator<String> partsComparator = getPartsNameComparator();
        
        return changeList.stream()
                .sorted(Comparator
                        .comparing(ActivitiDataDTO::getSubsystemName, collator)
                        .thenComparing(ActivitiDataDTO::getPartsName, partsComparator)
                        .thenComparing(ActivitiDataDTO::getParameterName, collator)
                )
                .collect(Collectors.toList());
    }
}