package com.xdap.self_development.service.impl;

import com.alibaba.fastjson2.JSON;
import com.definesys.mpaas.query.db.PageQueryResult;
import com.xdap.api.moudle.user.pojo.XdapUsers;
import com.xdap.self_development.common.BusinessDatabase;
import com.xdap.self_development.controller.form.*;
import com.xdap.self_development.domain.dto.ApprovalNodeDTO;
import com.xdap.self_development.domain.dto.ApprovalNodesDTO;
import com.xdap.self_development.domain.pojo.*;
import com.xdap.self_development.domain.view.ApprovalFlowNodeView;
import com.xdap.self_development.domain.view.FlowNode;
import com.xdap.self_development.domain.view.TemplateChangeView;
import com.xdap.self_development.domain.view.TodoAndTemplateView;
import com.xdap.self_development.exception.CommonException;
import com.xdap.self_development.service.TemplateApprovalService;
import com.xdap.self_development.service.XdapDeptUsersService;
import com.xdap.self_development.utils.RedisLockUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.Timestamp;
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 TemplateApprovalServiceImpl implements TemplateApprovalService {
    @Resource
    private BusinessDatabase bd;
    @Resource
    private RedisLockUtils redisLockUtil;
    @Resource
    private XdapDeptUsersService xdapDeptUsersService;
    @Resource
    private TemplateApprovalService myself;

    // 分布式锁标志
    private static final String FLOW_LOCK_PREFIX = "approval:lock:";
    // 分布式锁有效时间
    private static final int FLOW_LOCK_EXPIRE_SECONDS = 5;

    @Override
    @Transactional
    /**
     * 开始审批流程
     *
     * @param request 启动审批请求对象
     * @return 审批流程ID
     */
    public String startApproval(StartApprovalRequest request) {
        // 验证能否发起审批
        TemplatePojo template = bd.getBusinessDatabase()
                .rowid("id", request.getTemplateRowId())
                .doQueryFirst(TemplatePojo.class);
        if (template == null) {
            throw new CommonException("模板不存在");
        }

        if (!Objects.equals("DRAFT", template.getStatus())) {
            throw new CommonException("非草稿不允许发起审批");
        }

        List<TemplatePojo> templates = bd.getBusinessDatabase()
                .eq("template_name", template.getTemplateName())
                .orderBy("version", "asc").doQuery(TemplatePojo.class);
        boolean approving = templates.stream().map(TemplatePojo::getStatus)
                .collect(Collectors.toList()).contains("APPROVING");
        if (approving) {
            throw new CommonException("同名模板已在审核中");
        }

        List<TemplateAndParameterPojo> templateAndParameters = bd.getBusinessDatabase()
                .eq("template_id", template.getId()).doQuery(TemplateAndParameterPojo.class);

        if (templateAndParameters.isEmpty()) {
            throw new CommonException("空参数模板不允许发起审批");
        }

        // 清除拒绝提醒待办
        ApprovalFlowPojo historyFlow = bd.getBusinessDatabase()
                .eq("template_id", template.getId())
                .in("flow_status", "REJECTED", "RETURNED")
                .doQueryFirst(ApprovalFlowPojo.class);
        if (historyFlow != null) {
            bd.getBusinessDatabase()
                    .eq("document_no", historyFlow.getId())
                    .eq("data_type", "模板拒绝")
                    .update("is_delete", 1)
                    .doUpdate(TodoTaskPojo.class);
        }

        // 新增流程
        ApprovalFlowPojo flow = new ApprovalFlowPojo();
        flow.setTemplateId(template.getId());
        flow.setCurrentNode(1);
        flow.setFlowStatus("APPROVING");
        flow.setProcessTitle(request.getProcessTitle());
        flow.setCreateBy(request.getUserId());
        flow.setCreatedTime(Timestamp.valueOf(LocalDateTime.now()));
        flow.setFlowType(1); // 设置为模板审批流程
        flow.setExplanation(request.getExplanation());
        flow.setReturnNum(template.getReturnNum());
        flow.setPreNode(-1);// 标识没有退回节点
        bd.getBusinessDatabase().doInsert(flow);

        // 新增流程配置
        List<ApprovalConfigPojo> approvalConfigs = new ArrayList<>();
        ApprovalNodeDTO firstNode = new ApprovalNodeDTO();
        boolean hasUsers = false;
        int step = 0;
        for (ApprovalNodeDTO node : request.getNodeList()) {
            if (node.getAssignees().isEmpty()) {
                hasUsers = true;
                step++;
                continue;
            }
            if (hasUsers) {
                node.setNodeOrder(node.getNodeOrder() - step);
                hasUsers = false;
                step = 0;
            }
            if (node.getNodeOrder() == 1) {
                firstNode.setNodeOrder(1);
                firstNode.setAssignees(node.getAssignees());
                firstNode.setNodeName(node.getNodeName());
            }
            ApprovalConfigPojo config = new ApprovalConfigPojo();
            config.setNodeName(node.getNodeName());
            config.setNodeOrder(node.getNodeOrder());
            config.setAssignees(JSON.toJSONString(node.getAssignees()));
            config.setApprovalId(flow.getId());
            approvalConfigs.add(config);
        }
        bd.getBusinessDatabase().doBatchInsert(approvalConfigs);

        // 新增我的待办
        List<TodoTaskPojo> list = new ArrayList<>();
        for (String person : firstNode.getAssignees()) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(request.getUserId());
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(request.getUserId()).getUsername());
            todoTask.setCurrentNode(firstNode.getNodeName());
            todoTask.setDataType("模板审核");
            todoTask.setDocumentNo(flow.getId());
            todoTask.setCreationDate(flow.getCreatedTime());
            todoTask.setIsDelete(0);
            todoTask.setModelId(template.getId());
            todoTask.setModelName(template.getTemplateName());
            todoTask.setProcessTitle(request.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(template.getVersion());
            todoTask.setOwnerId(person);
            todoTask.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees()));
            list.add(todoTask);
        }
        bd.getBusinessDatabase().doBatchInsert(list);

        // 新增我创建的
        InitiatedTaskPojo initiatedTask = new InitiatedTaskPojo();
        initiatedTask.setDocumentNo(flow.getId());
        initiatedTask.setCreatedById(flow.getCreateBy());
        initiatedTask.setCreatedBy(xdapDeptUsersService.selectUserByID(flow.getCreateBy()).getUsername());
        initiatedTask.setCurrentNode(firstNode.getNodeName());
        initiatedTask.setCurrentProcessor(JSON.toJSONString(firstNode.getAssignees()));
        initiatedTask.setDataType("模板审核");
        initiatedTask.setProcessTitle(request.getProcessTitle());
        initiatedTask.setCreationDate(flow.getCreatedTime());
        initiatedTask.setIsDelete(0);
        initiatedTask.setModelId(flow.getTemplateId());
        initiatedTask.setEnableReturn(1);
        bd.getBusinessDatabase().doInsert(initiatedTask);

        // 新增发起记录
        bd.getBusinessDatabase().doInsert(
                new ApprovalRecordPojo(
                        flow.getId(),
                        "发起审批",
                        xdapDeptUsersService.selectUserByID(request.getUserId()).getUsername(),
                        "发起审批",
                        "MSG",
                        Timestamp.valueOf(LocalDateTime.now()),
                        1
                )
        );


        // 更新模板状态为审批中
        template.setStatus("APPROVING");
        bd.getBusinessDatabase()
                .rowid("id", template.getRowId())
                .update("status", template.getStatus())
                .doUpdate(TemplatePojo.class);
        return flow.getId();
    }

    @Override
    @Transactional
    /**
     * 继续审批流程
     *
     * @param flowId 流程ID
     * @param userId 用户ID
     */
    public void continueApproval(String flowId, String userId) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow == null) {
            throw new CommonException("流程不存在");
        }

        if ("APPROVING".equals(flow.getFlowStatus())) {
            throw new CommonException("流程正在审批中");
        }

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

        // 修改非进行中的流程为进行中
        ApprovalConfigPojo firstNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .orderBy("node_order", "asc")
                .doQueryFirst(ApprovalConfigPojo.class);
        if (!Objects.equals(flow.getFlowStatus(), "APPROVING")) {
            flow.setPreNode(-1);
            flow.setFlowStatus("APPROVING");
            flow.setCurrentNode(firstNode.getNodeOrder());

            bd.getBusinessDatabase()
                    .eq("id", flow.getId())
                    .update("flow_status", "APPROVING")
                    .update("current_node", firstNode.getNodeOrder())
                    .update("pre_node", -1)
                    .doUpdate(ApprovalFlowPojo.class);
        }

        // 获取当前节点和模板
        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(TemplatePojo.class);

        // 添加新待办
        List<TodoTaskPojo> list = new ArrayList<>();
        for (String person : JSON.parseArray(firstNode.getAssignees()).toJavaList(String.class)) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(userId);
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(userId).getUsername());
            todoTask.setCurrentNode(firstNode.getNodeName());
            todoTask.setDataType("模板审核");
            todoTask.setDocumentNo(flow.getId());
            todoTask.setCreationDate(flow.getCreatedTime());
            todoTask.setIsDelete(0);
            todoTask.setModelId(template.getId());
            todoTask.setModelName(template.getTemplateName());
            todoTask.setProcessTitle(flow.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(template.getVersion());
            todoTask.setOwnerId(person);
            todoTask.setCurrentProcessor(firstNode.getAssignees());
            list.add(todoTask);
        }
        bd.getBusinessDatabase().doBatchInsert(list);

        ApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("flow_id", flow.getId())
                .orderBy("approval_time", "desc")
                .doQueryFirst(ApprovalRecordPojo.class);
        bd.getBusinessDatabase().doInsert(
                new ApprovalRecordPojo(
                        flow.getId(),
                        "重新发起",
                        xdapDeptUsersService.selectUserByID(userId).getUsername(),
                        "重新发起",
                        "MSG",
                        Timestamp.valueOf(LocalDateTime.now()),
                        lastedRecord.getApprovalLevel() + 1
                )
        );

        myself.updateTasks(flow, firstNode.getNodeName(), 0, firstNode);
    }

    @Override
    @Transactional
    /**
     * 直送审批
     *
     * @param templateId 模板ID
     * @param userId 用户ID
     */
    public void directSendingApproval(String templateId, String userId) {
        // 获取模板
        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", templateId)
                .doQueryFirst(TemplatePojo.class);
        if (template == null) {
            throw new CommonException("模板不存在");
        }

        // 获取到模板最近一次未完成的流程
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("template_id", templateId)
                .ne("pre_node", -1)
                .ne("flow_status", "COMPLETE")
                .orderBy("created_time", "desc")
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow == null) {
            throw new CommonException("流程没有直送节点");
        }

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

        // 删除当前节点待办
        if (currentNode != null) {
            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);
        ApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("flow_id", flow.getId())
                .orderBy("approval_time", "desc")
                .doQueryFirst(ApprovalRecordPojo.class) ;
        Integer level = Objects.equals(lastedRecord.getResult(), "MSG") ? lastedRecord.getApprovalLevel() : lastedRecord.getApprovalLevel() + 1;

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

        bd.getBusinessDatabase()
                .eq("id", flow.getId())
                .update("flow_status", "APPROVING")
                .update("current_node", flow.getPreNode())
                .update("pre_node", -1)
                .doUpdate(ApprovalFlowPojo.class);

        bd.getBusinessDatabase()
                .eq("id", template.getId())
                .update("status", "APPROVING")
                .doUpdate(TemplatePojo.class);

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

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

    // 查询所有流程
    @Override
    /**
     * 获取审批列表
     *
     * @param form 审批列表表单
     * @return 待办和模板视图分页结果
     */
    public PageQueryResult<TodoAndTemplateView> getApprovalList(ApprovalListForm form) {
        List<String> ids = bd.getSystemDatabase()
                .like("username", form.getUsername())
                .eq("exit_status", "ENABLE")
                .doQuery(XdapUsers.class).stream()
                .map(XdapUsers::getId).collect(Collectors.toList());
        PageQueryResult<TodoAndTemplateView> result = bd.getBusinessDatabase()
                .viewQueryMode(true)
                .view("getAllApproval")
                .setVar("templateName", form.getTemplateName())
                .setVar("status", form.getStatus())
                .setVar("createdTime", form.getCreateDate() == null ? "" : form.getCreateDate())
                .setVar("ids", ids)
                .doPageQuery(form.getPageNumber(), form.getPageSize(), TodoAndTemplateView.class);
        setCurrentApprovers(result);
        return result;
    }

    private void setCurrentApprovers(PageQueryResult<TodoAndTemplateView> result) {
        result.getResult().forEach(item -> {
            XdapUsers user = bd.getSystemDatabase()
                    .eq("id", item.getCreateBy())
                    .doQueryFirst(XdapUsers.class);
            item.setUsername(user == null ? "未找到用户-" + item.getCreateBy() : user.getUsername());
            if (item.getCurrentUsers() == null || item.getCurrentUsers().isEmpty()) {
                item.setCurrentApprovers(null);
                item.setCurrentUsers(null);
            } else {
                List<String> userIds = JSON.parseArray(item.getCurrentUsers()).toJavaList(String.class);
                List<ApprovalXdapUsersPojo> approvalXdapUsers = bd.getSystemDatabase()
                        .in("id", userIds)
                        .doQuery(ApprovalXdapUsersPojo.class);
                item.setCurrentApprovers(approvalXdapUsers);
                item.setCurrentUsers(null);
            }
        });
    }

    @Override
    @Transactional
    /**
     * 处理审批
     *
     * @param request 审批处理请求对象
     */
    public void handleApproval(HandleApprovalRequest request) {
        // 验证流程状态和用户权限
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", request.getFlowId())
                .eq("flow_type", 1)
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow == null || !"APPROVING".equals(flow.getFlowStatus())) {
            throw new CommonException("流程不存在或已结束");
        }
        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_order", flow.getCurrentNode())
                .doQueryFirst(ApprovalConfigPojo.class);
        if (!hasPermission(currentNode, request.getUserId())) {
            throw new CommonException("无权限处理或已被处理");
        }

        // 获取最新处理记录
        ApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("flow_id", flow.getId())
                .orderBy("approval_time", "desc")
                .doQueryFirst(ApprovalRecordPojo.class);

        // 处理审批节点
        if (!"会签".equals(currentNode.getNodeName())) {
            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 {
                // 抢签节点需要验证是否被处理
                int processedCount = bd.getBusinessDatabase()
                        .eq("flow_id", flow.getId())
                        .eq("node", currentNode.getNodeName())
                        .eq("approval_level", lastedRecord.getApprovalLevel())
                        .doQuery(ApprovalRecordPojo.class).size();
                if (processedCount > 0) {
                    throw new CommonException("此节点已被他人处理");
                }
                myself.processApprovalLogic(flow, request, currentNode, lastedRecord);
            } finally {
                redisLockUtil.unlock(lockKey, lockValue);
            }
        }
        // 会签节点
        else {
            myself.processApprovalLogic(flow, request, currentNode, lastedRecord);
        }
    }

    // 验证是否为当前处理人
    private boolean hasPermission(ApprovalConfigPojo node, String userId) {
        return JSON.parseArray(node.getAssignees())
                .toJavaList(String.class).contains(userId);
    }

    @Override
    public void processApprovalLogic(
            ApprovalFlowPojo flow,
            HandleApprovalRequest request,
            ApprovalConfigPojo currentNode,
            ApprovalRecordPojo lastedRecord
    ) {

        // 新增当前审批结果
        bd.getBusinessDatabase().doInsert(
                new ApprovalRecordPojo(
                        flow.getId(),
                        currentNode.getNodeName(),
                        request.getUserId(),
                        request.getOpinion(),
                        request.getResult(),
                        Timestamp.valueOf(LocalDateTime.now()),
                        lastedRecord == null ? 1 : 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(flow.getCreateBy());
        completedTaskPojo.setCreatedBy(xdapDeptUsersService.selectUserByID(flow.getCreateBy()).getUsername());
        completedTaskPojo.setCurrentNode(currentNode.getNodeName());
        completedTaskPojo.setCurrentProcessor(currentNode.getAssignees());
        completedTaskPojo.setDataType("模板审核");
        completedTaskPojo.setOwnerId(request.getUserId());
        completedTaskPojo.setProcessTitle(flow.getProcessTitle());
        completedTaskPojo.setCreationDate(flow.getCreatedTime());
        completedTaskPojo.setIsDelete(0);
        completedTaskPojo.setModelId(flow.getTemplateId());
        bd.getBusinessDatabase().doInsert(completedTaskPojo);


        // 处理驳回逻辑
        if ("REJECT".equals(request.getResult())) {
            // 审批人退回
            myself.cancelProcess(flow, currentNode, "REJECTED", request.getUserId());
            return;
        }
        // 处理通过逻辑，流转到下一节点
        myself.processNextNode(flow, currentNode, request.getUserId());
    }

    @Override
    public void cancelProcess(
            ApprovalFlowPojo flow,
            ApprovalConfigPojo node,
            String status,
            String userId
    ) {
        // 删除所有待办
        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);
        // 更新流程状态
        flow.setFlowStatus(status);
        bd.getBusinessDatabase()
                .rowid("id", flow.getRowId())
                .update("flow_status", flow.getFlowStatus())
                .update("return_num", flow.getReturnNum() + 1)
                .update("pre_node", node.getNodeOrder())
                .doUpdate(ApprovalFlowPojo.class);
        // 更新模板状态(重新打回草稿状态)
        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(TemplatePojo.class);
        template.setStatus("DRAFT");
        bd.getBusinessDatabase()
                .rowid("id", template.getRowId())
                .update("status", template.getStatus())
                .update("return_num", template.getReturnNum() + 1)
                .doUpdate(TemplatePojo.class);
        // 增加拒绝待办
        if (Objects.equals(status, "REJECTED")) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(userId);
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(userId).getUsername());
            todoTask.setCurrentNode("编制");
            todoTask.setDataType("模板拒绝");
            todoTask.setDocumentNo(flow.getId());
            todoTask.setCreationDate(flow.getCreatedTime());
            todoTask.setIsDelete(0);
            todoTask.setModelId(template.getId());
            todoTask.setModelName(template.getTemplateName());
            todoTask.setProcessTitle(flow.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(template.getVersion());
            todoTask.setOwnerId(flow.getCreateBy());
            todoTask.setCurrentProcessor(JSON.toJSONString(Collections.singletonList(flow.getCreateBy())));
            bd.getBusinessDatabase().doInsert(todoTask);
        }
        // 更新发起和已办
        myself.updateTasks(flow, "编制", 0, node);
    }

    // 处理下一节点流转
    @Override
    public void processNextNode(
            ApprovalFlowPojo flow,
            ApprovalConfigPojo currentNode,
            String userId
    ) {
        // 检查当前节点是否满足流转条件
        if (!myself.checkNodeComplete(flow, currentNode)) {
            return;
        }

        // 查询模板状态
        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(TemplatePojo.class);
        // 获取下一个节点
        ApprovalConfigPojo nextNode = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .eq("node_order", currentNode.getNodeOrder() + 1)
                .doQueryFirst(ApprovalConfigPojo.class);
        if (nextNode == null) {
            // 流程结束
            flow.setFlowStatus("COMPLETE");
            flow.setCurrentNode(null);
            template.setStatus("COMPLETE");
            // 将同名的上一个版本的状态改为历史
            bd.getBusinessDatabase()
                    .eq("template_name", template.getTemplateName())
                    .eq("version", template.getVersion() - 1)
                    .update("status", "HISTORY")
                    .doUpdate(TemplatePojo.class);
            // 将当前版本状态改为已发布
            bd.getBusinessDatabase()
                    .rowid("id", template.getRowId())
                    .update("status", template.getStatus())
                    .update("published_time", Timestamp.valueOf(LocalDateTime.now()))
                    .doUpdate(TemplatePojo.class);
            // 待办环节修改
            myself.updateTasks(flow, "已完成", 0, null);

        } else {
            flow.setCurrentNode(nextNode.getNodeOrder());
            myself.addNodeTodo(flow, nextNode, template, userId, 0);
        }

        bd.getBusinessDatabase()
                .rowid("id", flow.getRowId())
                .update("flow_status", flow.getFlowStatus())
                .update("current_node", flow.getCurrentNode())
                .update("pre_node", -1)
                .doUpdate(ApprovalFlowPojo.class);
    }

    // 检查节点是否完成
    @Override
    public boolean checkNodeComplete(ApprovalFlowPojo flow, ApprovalConfigPojo node) {
        ApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                .eq("flow_id", flow.getId())
                .orderBy("approval_time", "desc")
                .doQueryFirst(ApprovalRecordPojo.class);
        Integer processedCount = bd.getBusinessDatabase()
                .eq("flow_id", flow.getId())
                .eq("node", node.getNodeName())
                .eq("approval_level", lastedRecord.getApprovalLevel())
                .doQuery(ApprovalRecordPojo.class).size();
        if ("会签".equals(node.getNodeName())) {
            return processedCount.equals(JSON.parseArray(node.getAssignees()).size());
        } else {
            return processedCount >= 1;
        }
    }

    @Override
    public void addNodeTodo(
            ApprovalFlowPojo flow,
            ApprovalConfigPojo node,
            TemplatePojo template,
            String createBy,
            Integer enableReturn
    ) {
        // 获取处理人
        List<String> users = JSON.parseArray(node.getAssignees()).toJavaList(String.class);
        // 新增待办
        List<TodoTaskPojo> list = new ArrayList<>();
        for (String person : users) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(createBy);
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(createBy).getUsername());
            todoTask.setCurrentNode(node.getNodeName());
            todoTask.setDataType("模板审核");
            todoTask.setDocumentNo(flow.getId());
            todoTask.setCreationDate(flow.getCreatedTime());
            todoTask.setIsDelete(0);
            todoTask.setModelId(template.getId());
            todoTask.setModelName(template.getTemplateName());
            todoTask.setProcessTitle(flow.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(template.getVersion());
            todoTask.setOwnerId(person);
            todoTask.setCurrentProcessor(node.getAssignees());
            list.add(todoTask);
        }

        // 更新已办和发起的状态
        myself.updateTasks(flow, node.getNodeName(), enableReturn, node);

        if (!list.isEmpty()) {
            bd.getBusinessDatabase().doBatchInsert(list);
        }
    }

    @Override
    /**
     * 获取退回节点
     *
     * @param flowId 流程ID
     * @return 退回节点列表
     */
    public List<String> getReturnNodes(String flowId) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(ApprovalFlowPojo.class);
        return bd.getBusinessDatabase()
                .eq("approval_id", flowId)
                .lt("node_order", flow.getCurrentNode())
                .doQuery(ApprovalConfigPojo.class)
                .stream().sorted(Comparator.comparingInt(ApprovalConfigPojo::getNodeOrder))
                .collect(Collectors.toList())
                .stream().map(ApprovalConfigPojo::getNodeName)
                .collect(Collectors.toList());
    }

    @Override
    /**
     * 获取审批用户
     *
     * @param templateId 模板ID
     * @return 审批节点DTO
     */
    public ApprovalNodesDTO getApprovalUsers(String templateId) {
        ApprovalNodesDTO nodes = new ApprovalNodesDTO();
        nodes.setProcessTitle("");
        nodes.setExplanation("");
        nodes.setFlowId(null);
        List<ApprovalUserNodeDTO> list = new ArrayList<>();

        // 获取到模板最近一次未完成的流程
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("template_id", templateId)
                .ne("pre_node", -1)
                .ne("flow_status", "COMPLETE")
                .orderBy("created_time", "desc")
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow == null) {
            nodes.setNodeList(list);
            return nodes;
        }
        nodes.setFlowId(flow.getId());

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

        approvalConfigs.forEach(node -> {
            ApprovalUserNodeDTO dto = new ApprovalUserNodeDTO();
            List<String> userIds = JSON.parseArray(node.getAssignees()).toJavaList(String.class);
            dto.setNodeName(node.getNodeName());
            dto.setNodeOrder(node.getNodeOrder());
            dto.setAssignees(
                    bd.getSystemDatabase()
                            .in("id", userIds)
                            .doQuery(XdapUsers.class)
            );
            list.add(dto);
        });
        nodes.setProcessTitle(flow.getProcessTitle());
        nodes.setExplanation(flow.getExplanation());
        nodes.setNodeList(list);
        return nodes;
    }

    @Override
    /**
     * 获取是否直送
     *
     * @param flowId 流程ID
     * @return 是否直送
     */
    public boolean getIsDirect(String flowId) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(ApprovalFlowPojo.class);

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

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

    @Override
    @Transactional
    /**
     * 更新流程标题
     *
     * @param flowId 流程ID
     * @param title 流程标题
     */
    public void updateFlowTitle(String flowId, String title) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .ne("flow_status", "COMPLETE")
                .doQueryFirst(ApprovalFlowPojo.class);

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

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

        bd.getBusinessDatabase()
                .eq("id", flowId)
                .update("process_title", title)
                .doUpdate(ApprovalFlowPojo.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);
    }

    @Override
    /**
     * 获取可编辑节点
     *
     * @param flowId 流程ID
     * @return 可编辑节点列表
     */
    public List<String> getEditableNodes(String flowId) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .ne("flow_status", "COMPLETE")
                .doQueryFirst(ApprovalFlowPojo.class);

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

        List<ApprovalConfigPojo> nodes = bd.getBusinessDatabase()
                .eq("approval_id", flow.getId())
                .gteq("node_order", flow.getCurrentNode())
                .doQuery(ApprovalConfigPojo.class);

        if (nodes.isEmpty()) {
            return Collections.emptyList();
        }

        return nodes.stream().map(ApprovalConfigPojo::getNodeName).collect(Collectors.toList());
    }

    @Override
    @Transactional
    /**
     * 更新节点
     *
     * @param form 更新节点表单
     */
    public void updateNode(UpdateNodeForm form) {
        // 检查流程
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .ne("flow_status", "COMPLETE")
                .doQueryFirst(ApprovalFlowPojo.class);

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

        myself.updateNodeConfig(form);

        if (!Objects.equals(flow.getProcessTitle(), form.getTitle())) {
            bd.getBusinessDatabase()
                    .eq("id", flow.getId())
                    .update("process_title", form.getTitle())
                    .doUpdate(ApprovalFlowPojo.class);
        }
    }

    @Override
    /**
     * 更新节点配置
     *
     * @param form 更新节点表单
     */
    public void updateNodeConfig(UpdateNodeForm form) {
        // 获取可更新流程节点名称
        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(JSON.toJSONString(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", JSON.toJSONString(newNode.getAssignees()))
                        .doUpdate(ApprovalConfigPojo.class);
            } else {
                // 无节点增减时，只更新处理人
                bd.getBusinessDatabase()
                        .eq("id", node.getId())
                        .update("assignees", JSON.toJSONString(newNode.getAssignees()))
                        .doUpdate(ApprovalConfigPojo.class);
            }
        }
    }

    @Override
    /**
     * 更新任务
     *
     * @param flow 审批流程POJO
     * @param status 状态
     * @param enableReturn 是否启用退回
     * @param currentNode 当前节点
     */
    public void updateTasks(ApprovalFlowPojo flow, String status, Integer enableReturn, ApprovalConfigPojo currentNode) {
        // 更新已办和发起的节点状态
        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .update("current_processor", currentNode == null ? "" : currentNode.getAssignees())
                .update("current_node", status)
                .doUpdate(CompletedTaskPojo.class);
        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .update("current_node", status)
                .update("current_processor", currentNode == null ? "" : currentNode.getAssignees())
                .update("enable_return", enableReturn)
                .doUpdate(InitiatedTaskPojo.class);
    }

    @Override
    /**
     * 获取模板变更
     *
     * @param form 审批和参数表单
     * @return 模板变更视图分页结果
     */
    public PageQueryResult<TemplateChangeView> getTemplateChanges(ApprovalAndParameterForm form) {
        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", form.getTemplateId())
                .doQueryFirst(TemplatePojo.class);
        if (template == null) {
            throw new CommonException("模板不存在");
        }
        if (form.getFlowId() == null) {
            return bd.getBusinessDatabase()
                    .viewQueryMode(true)
                    .view("getParameterAndChange")
                    .setVar("templateId", form.getTemplateId())
                    .setVar("returnNum", template.getReturnNum())
                    .doPageQuery(form.getPageNumber(), form.getPageSize(), TemplateChangeView.class);
        } else {
            ApprovalFlowPojo approvalFlow = bd.getBusinessDatabase()
                    .eq("id", form.getFlowId())
                    .doQueryFirst(ApprovalFlowPojo.class);
            if (approvalFlow == null) {
                return bd.getBusinessDatabase()
                        .viewQueryMode(true)
                        .view("getParameterAndChange")
                        .setVar("templateId", form.getTemplateId())
                        .setVar("returnNum", template.getReturnNum())
                        .doPageQuery(form.getPageNumber(), form.getPageSize(), TemplateChangeView.class);
            } else {
                return bd.getBusinessDatabase()
                        .viewQueryMode(true)
                        .view("getParameterAndChange")
                        .setVar("templateId", form.getTemplateId())
                        .setVar("returnNum", approvalFlow.getReturnNum())
                        .doPageQuery(form.getPageNumber(), form.getPageSize(), TemplateChangeView.class);
            }
        }
    }

    @Override
    /**
     * 获取审批流程
     *
     * @param form 审批流程表单
     * @return 审批流程节点视图
     */
    public ApprovalFlowNodeView getApprovalProcess(ApprovalFlowForm form) {
        ApprovalFlowNodeView flowNodeView = new ApprovalFlowNodeView();
        ApprovalFlowPojo approvalFlow = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .doQueryFirst(ApprovalFlowPojo.class);
        // 无流程创建空返回
        if (approvalFlow == null) {
            return flowNodeView;
        }

        List<FlowNode> flowNodes = new ArrayList<>();

        List<ApprovalRecordPojo> allRecord = bd.getBusinessDatabase()
                .eq("flow_id", approvalFlow.getId())
                .orderBy("approval_time", "asc")
                .doQuery(ApprovalRecordPojo.class);

        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", approvalFlow.getTemplateId())
                .doQueryFirst(TemplatePojo.class);

        // 获取节点信息
        if (approvalFlow.getCurrentNode() != null) {
            ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                    .eq("approval_id", approvalFlow.getId())
                    .eq("node_order", approvalFlow.getCurrentNode())
                    .doQueryFirst(ApprovalConfigPojo.class);
            flowNodeView.setCurrentNode(currentNode.getNodeName());
            flowNodeView.setProcessor(getUserNames(
                    JSON.parseArray(currentNode.getAssignees()).toJavaList(String.class)
            ));
        } else {
            flowNodeView.setCurrentNode("无");
            flowNodeView.setProcessor("无");
        }

        // 获取流程信息
        flowNodeView.setProgressTitle(approvalFlow.getProcessTitle());
        flowNodeView.setContentName(template.getTemplateName());
        flowNodeView.setTemplateVersion(template.getVersion());
        flowNodeView.setExplanation(approvalFlow.getExplanation());
        flowNodeView.setFlowStatus(approvalFlow.getFlowStatus());
        flowNodeView.setCreateBy(xdapDeptUsersService.selectUserByID(approvalFlow.getCreateBy()).getUsername());
        flowNodeView.setCreateTime(approvalFlow.getCreatedTime());

        // 获取节点信息
        List<ApprovalConfigPojo> nodes = bd.getBusinessDatabase()
                .eq("approval_id", form.getFlowId())
                .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<ApprovalRecordPojo>> levelMap = allRecord.stream()
                .collect(Collectors.groupingBy(
                        ApprovalRecordPojo::getApprovalLevel,
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> list.stream()
                                        .sorted(Comparator.comparing(ApprovalRecordPojo::getApprovalTime))
                                        .collect(Collectors.toList())
                        )
                ));

        // 获取最大层级
        int maxLevel = levelMap.keySet().stream().max(Integer::compare).orElse(1);

        for (Map.Entry<Integer, List<ApprovalRecordPojo>> entry : levelMap.entrySet()) {
            // 获取到每一层
            int level = entry.getKey();
            Set<Integer> nodeList = new HashSet<>();
            List<ApprovalRecordPojo> records = entry.getValue();
            List<ApprovalRecordPojo> uniqueRecords = new ArrayList<>(records.stream()
                    .collect(Collectors.toMap(
                            ApprovalRecordPojo::getNode,
                            Function.identity(),
                            (first, second) -> first
                    ))
                    .values());
            uniqueRecords.forEach(approvalecord -> {
                ApprovalConfigPojo approvalConfigPojo = nodesMap.get(approvalecord.getNode());
                if (approvalConfigPojo != null) {
                    flowNodes.add(getFlowNodeView(approvalConfigPojo, form.getFlowId(), level));
                    nodeList.add(approvalConfigPojo.getNodeOrder());
                } else {
                    FlowNode flowNode = new FlowNode();
                    flowNode.setNode(approvalecord.getNode());
                    flowNode.setTodoUserName(approvalecord.getUserId());
                    flowNode.setResult(approvalecord.getResult());
                    flowNode.setApprovalTime(approvalecord.getApprovalTime());
                    flowNodes.add(flowNode);
                }
            });

            if (level == maxLevel && Objects.equals(approvalFlow.getFlowStatus(), "APPROVING") ) {
                // 最后一层，添加待处理信息
                nodes.forEach(node -> {
                    if (!nodeList.contains(node.getNodeOrder()) && node.getNodeOrder() >= approvalFlow.getCurrentNode()) {
                        flowNodes.add(getFlowNodeView(node, form.getFlowId(), maxLevel));
                    }
                });
            }
        }
        List<FlowNode> sortedNode = flowNodes.stream()
                .sorted(Comparator.comparing(FlowNode::getApprovalTime,
                                Comparator.nullsLast(Comparator.naturalOrder()))
                        .thenComparing(FlowNode::getNodeOrder))
                .collect(Collectors.toList());
        flowNodeView.setFlowNodes(sortedNode);
        return flowNodeView;
    }

    private FlowNode getFlowNodeView(
            ApprovalConfigPojo node,
            String flowId,
            int level
    ) {
        FlowNode nodeView = new FlowNode();
        if (Objects.equals(node.getNodeName(), "会签")) {
            List<ApprovalRecordPojo> records = bd.getBusinessDatabase()
                    .eq("flow_id", flowId)
                    .eq("node", node.getNodeName())
                    .eq("approval_level", level)
                    .doQuery(ApprovalRecordPojo.class);
            List<String> results = records.stream()
                    .map(ApprovalRecordPojo::getResult).collect(Collectors.toList());
            List<ApprovalRecordPojo> reversedTime = records.stream().sorted(Comparator
                    .comparing(ApprovalRecordPojo::getApprovalTime).reversed()).collect(Collectors.toList());
            if (records.size() == JSON.parseArray(node.getAssignees()).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(JSON.parseArray(node.getAssignees()).toJavaList(String.class)));
                nodeView.setTodoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class)));
                nodeView.setApprovalTime(reversedTime.get(0).getApprovalTime());
                nodeView.setOpinions(records.stream().map(approvalRecord ->
                        getUserNames(Collections.singletonList(approvalRecord.getUserId())) + ":" + (approvalRecord.getOpinion() == null ? "" : approvalRecord.getOpinion())).collect(Collectors.toList()));
            } else {
                // 节点未完成
                nodeView.setNodeOrder(node.getNodeOrder());
                nodeView.setNode(node.getNodeName());
                nodeView.setResult("待审批");
                List<String> includedIds = records.stream().map(ApprovalRecordPojo::getUserId).collect(Collectors.toList());
                nodeView.setTodoUserName(getUserNames(includedIds));
                nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class)));
            }
        } else {
            ApprovalRecordPojo flowRecord = bd.getBusinessDatabase()
                    .eq("flow_id", flowId)
                    .eq("node", node.getNodeName())
                    .eq("approval_level", level)
                    .doQueryFirst(ApprovalRecordPojo.class);
            nodeView.setNodeOrder(node.getNodeOrder());
            nodeView.setNode(node.getNodeName());
            if (flowRecord != null) {
                // 节点已完成
                nodeView.setResult(flowRecord.getResult());
                nodeView.setOpinions(Collections.singletonList(getUserNames(Collections.singletonList(flowRecord.getUserId())) + ":" + flowRecord.getOpinion()));
                nodeView.setApprovalTime(flowRecord.getApprovalTime());
                nodeView.setTodoUserName(getUserNames(Collections.singletonList(flowRecord.getUserId())));
            } else {
                // 节点未完成
                nodeView.setResult("待审批");
                nodeView.setTodoUserName("");
            }
            nodeView.setUndoUserName(getUserNames(JSON.parseArray(node.getAssignees()).toJavaList(String.class)));
        }
        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();
    }

    @Override
    @Transactional
    public void handleReturn(HandleApprovalRequest request) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", request.getFlowId())
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow == null) {
            throw new CommonException("流程不存在");
        }
        if (!Objects.equals(flow.getCreateBy(), request.getUserId())) {
            throw new CommonException("不是申请人无法撤回");
        }
        if (!Objects.equals(flow.getFlowStatus(), "APPROVING")) {
            throw new CommonException("不在流程无法撤回");
        }
        ApprovalConfigPojo currentNode = bd.getBusinessDatabase()
                .eq("approval_id", request.getFlowId())
                .eq("node_order", flow.getCurrentNode())
                .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())) {
                ApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                        .eq("flow_id", flow.getId())
                        .orderBy("approval_time", "desc")
                        .doQueryFirst(ApprovalRecordPojo.class);

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

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

    @Override
    @Transactional
    public void handleReturnToNode(HandleReturnNodeForm form) {
        // 查找流程
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .doQueryFirst(ApprovalFlowPojo.class);

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

        // 查找模板
        TemplatePojo template = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(TemplatePojo.class);

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

        if (!currentNode.getAssignees().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", flow.getCurrentNode())
                    .doUpdate(ApprovalFlowPojo.class);

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

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