package com.xdap.self_development.service.impl;

import cn.hutool.core.codec.Base64;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.definesys.mpaas.query.db.PageQueryResult;
import com.xdap.api.moudle.user.pojo.XdapUsers;
import com.xdap.runtime.service.RuntimeAppContextService;
import com.xdap.self_development.common.BusinessDatabase;
import com.xdap.self_development.controller.form.*;
import com.xdap.self_development.domain.dto.*;
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.TodoAndReportListView;
import com.xdap.self_development.domain.view.TodoAndReportView;
import com.xdap.self_development.exception.CommonException;
import com.xdap.self_development.feign.ApaasMyTokenFeign;
import com.xdap.self_development.service.BenchmarkingReportService;
import com.xdap.self_development.service.XdapDeptUsersService;
import com.xdap.self_development.utils.RedisLockUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

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
public class  BenchmarkingReportServiceImpl implements BenchmarkingReportService {
    @Resource
    private BusinessDatabase bd;
    @Resource
    private RuntimeAppContextService runtimeAppContextService;
    @Autowired
    private ApaasMyTokenFeign apaasMyTokenFeign;
    @Resource
    private RedisLockUtils redisLockUtil;
    @Resource
    private XdapDeptUsersService xdapDeptUsersService;
    @Resource
    private BenchmarkingReportService myself;

    @Value("${apaas.token.clientId}")
    private String clientId;
    @Value("${apaas.token.clientSecred}")
    private String clientSecret;

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


    /**
     * 插入报告
     * 创建新的对标报告并启动审批流程
     *
     * @param form 保存对标报告表单
     * @return void
     */
    @Override
    @Transactional
    public void insertReport(SaveBenchmarkingReportForm form) {
        // 创建报告
        BenchmarkingReportPojo report = new BenchmarkingReportPojo();
        BeanUtils.copyProperties(form, report);
        report.setFilePath(form.getFileUrl() == null ? "" : form.getFileUrl());
        report.setUploadTime(Timestamp.valueOf(LocalDateTime.now()));
        // 草稿状态
        report.setStatus("DRAFT");
        report.setCreateBy(form.getUserId());
        report.setIsDelete(0);
        report.setReturnNum(0);
        report.setFileName(form.getFileName());
        bd.getBusinessDatabase().doInsert(report);

        // 新增流程
        ApprovalFlowPojo flow = new ApprovalFlowPojo();
        flow.setTemplateId(report.getId());
        flow.setCurrentNode(1);
        flow.setFlowStatus("DRAFT");
        flow.setProcessTitle(form.getProcessTitle());
        flow.setCreateBy(form.getUserId());
        flow.setCreatedTime(Timestamp.valueOf(LocalDateTime.now()));
        flow.setFlowType(2); // 设置为报告审批流程
        flow.setExplanation(form.getExplanation());
        flow.setReturnNum(0);
        flow.setPreNode(-1);
        bd.getBusinessDatabase().doInsert(flow);

        // 创建审批配置
        List<ApprovalConfigPojo> approvalConfigs = new ArrayList<>();
        for (ApprovalNodeDTO node : form.getNodeList()) {
            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);
    }

    /**
     * 更新报告
     * 修改已有对标报告的信息
     *
     * @param form 更新对标报告表单
     * @return void
     */
    @Override
    public void updateReport(UpdateBenchmarkingReportForm form) {
        // 验证报告
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", form.getReportId())
                .doQueryFirst(BenchmarkingReportPojo.class);
        if (!"DRAFT".equals(report.getStatus()) && !"REJECTED".equals(report.getStatus())) {
            throw new CommonException("报告非草稿或拒绝状态不可修改");
        }
        if (!Objects.equals(report.getCreateBy(), form.getUserId())) {
            throw new CommonException("非创建者不能修改");
        }
        // 修改报告
        BeanUtils.copyProperties(form, report);
        report.setFilePath(form.getFileUrl() == null ? "" : form.getFileUrl());
        report.setUploadTime(Timestamp.valueOf(LocalDateTime.now()));
        report.setStatus("DRAFT");
        bd.getBusinessDatabase()
                .eq("id", report.getId())
                .doUpdate(report);
    }

    /**
     * 删除报告
     * 逻辑删除指定ID的对标报告
     *
     * @param reportId 报告ID
     * @return void
     */
    @Override
    @Transactional
    public void deleteReport(String reportId) {
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", reportId)
                .doQueryFirst(BenchmarkingReportPojo.class);
        if (report == null) {
            throw new CommonException("该报告不存在");
        }
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("template_id", reportId)
                .ne("pre_node", -1)
                .eq("flow_status", "APPROVING")
                .orderBy("created_time", "desc")
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow != null) {
            throw new CommonException("该报告正在审批中");
        }
        bd.getBusinessDatabase()
                .eq("id", reportId)
                .update("is_delete", 1)
                .doUpdate(BenchmarkingReportPojo.class);
    }

    /**
     * 上传文件
     * 将文件上传到服务器并返回访问路径
     *
     * @param file   文件对象
     * @param userId 用户ID
     * @return 文件访问路径
     */
    @Override
    public String uploadFile(MultipartFile file, String userId) {
        try {
            String currentTenantId = runtimeAppContextService.getCurrentTenantId();
            AppTokenDTO token = apaasMyTokenFeign.getAppToken(
                    "client_credentials",
                    clientId,
                    clientSecret
            );
            if (token == null || token.getAccess_token() == null) {
                throw new CommonException("文件上传失败");
            }
            UserTokenDT0 userToken = apaasMyTokenFeign.getUserToken(
                    token.getAccess_token(),
                    userId
            );
            if (userToken == null || userToken.getAccess_token() == null) {
                throw new CommonException("文件上传失败");
            }
            String uploadId = new ObjectId().toHexString();
            FileUploadDTO fileUploadDTO = apaasMyTokenFeign.uploadFile(
                    "Bearer " + userToken.getAccess_token(),
                    file,
                    uploadId,
                    currentTenantId,
                    userId
            );
            if (fileUploadDTO == null || fileUploadDTO.getData() == null) {
                throw new CommonException("文件上传失败");
            }
            Map<String, String> map = new HashMap<>();
            map.put("xdaptenantid", currentTenantId);
            cn.hutool.json.JSON json = JSONUtil.parse(map);
            String tokenXdap = Base64.encode(json.toString());
            return fileUploadDTO.getData().getUrl() + "&download=download&token=" + tokenXdap;
        } catch (Exception e) {
            throw new CommonException(e.getMessage());
        }
    }

    /**
     * 启动报告审批
     * 开始对标报告的审批流程
     *
     * @param form 审批人员表单
     * @return void
     */
    @Override
    @Transactional
    public void startReportApproval(ApprovalPersonForm form) {
        // 验证能否发起审批
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", form.getReportId())
                .doQueryFirst(BenchmarkingReportPojo.class);
        if (report == null) {
            throw new CommonException("该报告不存在");
        }

        ApprovalFlowPojo approvalFlow = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .doQueryFirst(ApprovalFlowPojo.class);
        if (approvalFlow == null || Objects.equals(approvalFlow.getFlowStatus(), "APPROVING")) {
            throw new CommonException("该报告正在审批中");
        }

        // 清除拒绝提醒待办
        ApprovalFlowPojo historyFlow = bd.getBusinessDatabase()
                .eq("template_id", report.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);
        }

        // 更新流程状态
        bd.getBusinessDatabase()
                .eq("id", approvalFlow.getId())
                .update("flow_status", "APPROVING")
                .update("current_node", 1)
                .update("pre_node", -1)
                .doUpdate(ApprovalFlowPojo.class);

        // 获取首个节点
        ApprovalConfigPojo firstNode = bd.getBusinessDatabase()
                .eq("approval_id", approvalFlow.getId())
                .eq("node_order", 1)
                .doQueryFirst(ApprovalConfigPojo.class);


        // 新增我的待办
        List<TodoTaskPojo> list = new ArrayList<>();
        for (String person : JSON.parseArray(firstNode.getAssignees()).toJavaList(String.class)) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(form.getUserId());
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(form.getUserId()).getUsername());
            todoTask.setCurrentNode(firstNode.getNodeName());
            todoTask.setDataType("对标报告审核");
            todoTask.setDocumentNo(approvalFlow.getId());
            todoTask.setCreationDate(approvalFlow.getCreatedTime());
            todoTask.setIsDelete(0);
            todoTask.setModelId(report.getId());
            todoTask.setModelName(report.getProjectName() + "对标报告");
            todoTask.setProcessTitle(approvalFlow.getProcessTitle());
            todoTask.setStatusCode(approvalFlow.getFlowStatus());
            todoTask.setVersionNumber(1);
            todoTask.setOwnerId(person);
            todoTask.setCurrentProcessor(firstNode.getAssignees());
            list.add(todoTask);
        }
        bd.getBusinessDatabase().doBatchInsert(list);

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

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

        // 更新报告状态为校对中
        bd.getBusinessDatabase()
                .eq("id", report.getId())
                .update("status", "APPROVING")
                .doUpdate(BenchmarkingReportPojo.class);
    }

    /**
     * 继续审批
     * 继续执行对标报告的审批流程
     *
     * @param flowId 流程ID
     * @param userId 用户ID
     * @return void
     */
    @Override
    @Transactional
    public void continueApproval(String flowId, String userId) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .doQueryFirst(ApprovalFlowPojo.class);
        if (flow == null) {
            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);
        }

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

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

        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
                )
        );
    }

    /**
     * 重启报告审批
     * 重新启动对标报告的审批流程
     *
     * @param form 重启报告审批表单
     * @return void
     */
    @Override
    @Transactional
    public void restartReportApproval(RestartReportApprovalForm form) {
        // 获取报告
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", form.getReportId())
                .doQueryFirst(BenchmarkingReportPojo.class);

        if (report == null) {
            throw new CommonException("报告不存在");
        }

        ApprovalFlowPojo historyFlow = bd.getBusinessDatabase()
                .eq("template_id", report.getId())
                .eq("flow_status", "APPROVING")
                .doQueryFirst(ApprovalFlowPojo.class);
        if (historyFlow != null) {
            throw new CommonException("报告正在审批中");
        }

        // 修改报告
        BeanUtils.copyProperties(form, report);
        report.setFilePath(form.getFileUrl() == null ? "" : form.getFileUrl());
        report.setUploadTime(Timestamp.valueOf(LocalDateTime.now()));
        report.setStatus("DRAFT");
        bd.getBusinessDatabase()
                .eq("id", report.getId())
                .doUpdate(report);

        // 清除拒绝提醒待办
        ApprovalFlowPojo approvalFlow = bd.getBusinessDatabase()
                .eq("template_id", report.getId())
                .in("flow_status", "REJECTED", "RETURNED")
                .doQueryFirst(ApprovalFlowPojo.class);
        bd.getBusinessDatabase()
                .eq("document_no", approvalFlow.getId())
                .eq("data_type", "对标报告拒绝")
                .update("is_delete", 1)
                .doUpdate(TodoTaskPojo.class);

        // 新增流程
        ApprovalFlowPojo flow = new ApprovalFlowPojo();
        flow.setTemplateId(report.getId());
        flow.setCurrentNode(1);
        flow.setFlowStatus("APPROVING");
        flow.setProcessTitle(form.getProcessTitle());
        flow.setCreateBy(form.getUserId());
        flow.setCreatedTime(Timestamp.valueOf(LocalDateTime.now()));
        flow.setFlowType(2); // 设置为报告审批流程
        flow.setExplanation(form.getExplanation());
        flow.setReturnNum(0);
        flow.setPreNode(-1);
        bd.getBusinessDatabase().doInsert(flow);

        // 创建审批配置
        List<ApprovalConfigPojo> approvalConfigs = new ArrayList<>();
        for (ApprovalNodeDTO node : form.getNodeList()) {
            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);

        // 发起流程
        ApprovalPersonForm newForm = new ApprovalPersonForm();
        newForm.setUserId(form.getUserId());
        newForm.setFlowId(flow.getId());
        newForm.setReportId(report.getId());
        // 更新流程状态
        bd.getBusinessDatabase()
                .eq("id", newForm.getFlowId())
                .update("flow_status", "APPROVING")
                .update("current_node", 1)
                .update("pre_node", -1)
                .doUpdate(ApprovalFlowPojo.class);

        // 获取首个节点
        ApprovalConfigPojo firstNode = bd.getBusinessDatabase()
                .eq("approval_id", newForm.getFlowId())
                .eq("node_order", 1)
                .doQueryFirst(ApprovalConfigPojo.class);


        // 新增我的待办
        List<TodoTaskPojo> list = new ArrayList<>();
        for (String person : JSON.parseArray(firstNode.getAssignees()).toJavaList(String.class)) {
            TodoTaskPojo todoTask = new TodoTaskPojo();
            todoTask.setCreatedById(newForm.getUserId());
            todoTask.setCreatedBy(xdapDeptUsersService.selectUserByID(newForm.getUserId()).getUsername());
            todoTask.setCurrentNode(firstNode.getNodeName());
            todoTask.setDataType("对标报告审核");
            todoTask.setDocumentNo(newForm.getFlowId());
            todoTask.setCreationDate(flow.getCreatedTime());
            todoTask.setIsDelete(0);
            todoTask.setModelId(report.getId());
            todoTask.setModelName(report.getProjectName() + "对标报告");
            todoTask.setProcessTitle(flow.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(1);
            todoTask.setOwnerId(person);
            todoTask.setCurrentProcessor(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(firstNode.getAssignees());
        initiatedTask.setDataType("对标报告审核");
        initiatedTask.setProcessTitle(flow.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(newForm.getUserId()).getUsername(),
                        "发起审批",
                        "MSG",
                        Timestamp.valueOf(LocalDateTime.now()),
                        1
                )
        );

        // 更新报告状态为校对中
        bd.getBusinessDatabase()
                .eq("id", report.getId())
                .update("status", "APPROVING")
                .doUpdate(BenchmarkingReportPojo.class);
    }

    /**
     * 直接发送审批
     * 将审批流程直接发送到指定节点
     *
     * @param reportId 报告ID
     * @param userId   用户ID
     * @return void
     */
    @Override
    @Transactional
    public void directSendingApproval(String reportId, String userId) {
        // 获取报告
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", reportId)
                .doQueryFirst(BenchmarkingReportPojo.class);
        if (report == null) {
            throw new CommonException("报告不存在");
        }

        // 获取到模板最近一次未完成的流程
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("template_id", reportId)
                .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,
                report,
                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", report.getId())
                .update("status", "APPROVING")
                .doUpdate(BenchmarkingReportPojo.class);

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

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

    /**
     * 处理退回至节点
     * 将审批流程退回至指定节点
     *
     * @param form 退回节点表单
     * @return void
     */
    @Override
    @Transactional
    public void handleReturnToNode(HandleReturnNodeForm form) {
        // 查找流程
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", form.getFlowId())
                .doQueryFirst(ApprovalFlowPojo.class);

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

        // 查找模板
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(BenchmarkingReportPojo.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, report, form.getCreateUserId(), 1);

            // 生成处理记录
            ApprovalRecordPojo lastedRecord = bd.getBusinessDatabase()
                    .eq("flow_id", flow.getId())
                    .orderBy("approval_time", "desc")
                    .doQueryFirst(ApprovalRecordPojo.class);
            ApprovalRecordPojo approvalRecordPojo = new ApprovalRecordPojo(
                    flow.getId(),
                    currentNode.getNodeName(),
                    form.getProcessUserId(),
                    "退回",
                    "RETURN",
                    Timestamp.valueOf(LocalDateTime.now()),
                    lastedRecord.getApprovalLevel()
            );
            bd.getBusinessDatabase().doInsert(approvalRecordPojo);
            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);
        }
    }

    /**
     * 处理退回
     * 处理对标报告审批的退回操作
     *
     * @param request 审批请求
     * @return void
     */
    @Override
    @Transactional
    public void handleReturn(HandleApprovalRequest request) {
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", request.getFlowId())
                .doQueryFirst(ApprovalFlowPojo.class);
        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);
        }
    }

    /**
     * 获取审批列表
     * 获取对标报告的审批列表信息
     *
     * @param form 审批列表表单
     * @return 待办和报告列表视图的分页查询结果
     */
    @Override
    public PageQueryResult<TodoAndReportListView> 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<TodoAndReportListView> result = bd.getBusinessDatabase()
                .viewQueryMode(true)
                .view("getAllReportApprovalList")
                .setVar("title", form.getTemplateName())
                .setVar("status", form.getStatus())
                .setVar("createdTime", form.getCreateDate() == null ? "" : form.getCreateDate())
                .setVar("ids", ids)
                .doPageQuery(form.getPageNumber(), form.getPageSize(), TodoAndReportListView.class);
        setApprovalCurrentUser(result);
        return result;
    }

    /**
     * 设置审批当前用户
     * 为审批列表设置当前用户信息
     *
     * @param result 待办和报告列表视图的分页查询结果
     * @return void
     */
    private void setApprovalCurrentUser(PageQueryResult<TodoAndReportListView> result) {
        result.getResult().forEach(item -> {
            ApprovalXdapUsersPojo approvalXdapUser = bd.getSystemDatabase()
                    .eq("id", item.getCreateBy())
                    .doQueryFirst(ApprovalXdapUsersPojo.class);
            if (approvalXdapUser == null || approvalXdapUser.getUsername() == null) {
                item.setUsername("未知用户-" + item.getCreateBy());
            } else {
                item.setUsername(approvalXdapUser.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);
            }
        });
    }

    /**
     * 根据条件获取对标报告
     * 根据筛选条件查询对标报告列表
     *
     * @param form 对标报告页面表单
     * @return 待办和报告视图的分页查询结果
     */
    @Override
    public PageQueryResult<TodoAndReportView> getBenchmarkingReportByCondition(BenchmarkingReportPageForm form) {
        PageQueryResult<TodoAndReportView> result = bd.getBusinessDatabase()
                .viewQueryMode(true)
                .view("getAllReport")
                .setVar("title", form.getTitle())
                .setVar("manufacturerName", form.getManufacturerName())
                .setVar("modelName", form.getModelName())
                .setVar("productNumber", form.getProductNumber())
                .setVar("module", form.getModule())
                .setVar("plate", form.getPlate())
                .setVar("platform", form.getPlatform())
                .setVar("series", form.getSeries())
                .setVar("marketSegment", form.getMarketSegment())
                .setVar("projectName", form.getProjectName())
                .setVar("projectNumber", form.getProjectNumber())
                .setVar("status", form.getStatus())
                .doPageQuery(form.getPageNumber(), form.getPageSize(), TodoAndReportView.class);
        setCurrentApprovers(result);
        return result;
    }

    /**
     * 设置当前审批人
     * 为报告列表设置当前审批人信息
     *
     * @param result 待办和报告视图的分页查询结果
     * @return void
     */
    private void setCurrentApprovers(PageQueryResult<TodoAndReportView> result) {
        result.getResult().forEach(item -> {
            ApprovalXdapUsersPojo approvalXdapUser = bd.getSystemDatabase()
                    .eq("id", item.getCreateBy())
                    .doQueryFirst(ApprovalXdapUsersPojo.class);
            item.setCreateBy(approvalXdapUser == null ? item.getCreateBy() : approvalXdapUser.getUsername());
        });
    }

    /**
     * 处理报告审批
     * 处理对标报告的审批请求
     *
     * @param request 处理审批请求
     * @return void
     */
    @Override
    @Transactional
    public void handleReportApproval(HandleApprovalRequest request) {
        // 验证流程状态和用户权限
        ApprovalFlowPojo flow = bd.getBusinessDatabase()
                .eq("id", request.getFlowId())
                .eq("flow_type", 2)
                .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);

        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);
        }
    }

    /**
     * 验证是否有权限
     * 检查用户是否有处理当前节点的权限
     *
     * @param node   审批配置节点
     * @param userId 用户ID
     * @return 是否有权限
     */
    private boolean hasPermission(ApprovalConfigPojo node, String userId) {
        return JSON.parseArray(node.getAssignees())
                .toJavaList(String.class).contains(userId);
    }

    /**
     * 处理审批逻辑
     * 执行对标报告审批的核心逻辑
     *
     * @param flow          审批流程POJO
     * @param request       处理审批请求
     * @param currentNode   当前节点
     * @param lastedRecord  最后一条记录
     * @return void
     */
    @Override
    public void processApprovalLogic(
            ApprovalFlowPojo flow,
            HandleApprovalRequest request,
            ApprovalConfigPojo currentNode,
            ApprovalRecordPojo lastedRecord
    ) {
        // 记录审批结果
        ApprovalRecordPojo approvalRecordPojo = new ApprovalRecordPojo(
                flow.getId(),
                currentNode.getNodeName(),
                request.getUserId(),
                request.getOpinion(),
                request.getResult(),
                Timestamp.valueOf(LocalDateTime.now()),
                lastedRecord == null ? 1 : lastedRecord.getApprovalLevel()
        );
        bd.getBusinessDatabase().doInsert(approvalRecordPojo);

        bd.getBusinessDatabase()
                .eq("document_no", flow.getId())
                .eq("current_node", currentNode.getNodeName())
                .update("last_update_date", Timestamp.valueOf(LocalDateTime.now()))
                .update("is_delete", 1)
                .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());
    }

    /**
     * 处理下一个节点
     * 处理审批流程的下一个节点
     *
     * @param flow        审批流程POJO
     * @param currentNode 当前节点
     * @param userId      用户ID
     * @return void
     */
    @Override
    public void processNextNode(ApprovalFlowPojo flow, ApprovalConfigPojo currentNode, String userId) {
        // 查询报告状态
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(BenchmarkingReportPojo.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);
            report.setStatus("COMPLETE");
            bd.getBusinessDatabase()
                    .rowid("id", report.getRowId())
                    .update("status", report.getStatus())
                    .doUpdate(BenchmarkingReportPojo.class);
            // 待办环节修改
            myself.updateTasks(flow, "已完成", 0, null);
        } else {
            flow.setCurrentNode(nextNode.getNodeOrder());
            myself.addNodeTodo(flow, nextNode, report, userId, 0);
        }

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

    /**
     * 添加节点待办
     * 为指定节点添加待办任务
     *
     * @param flow         审批流程POJO
     * @param node         审批节点
     * @param report       对标报告POJO
     * @param createBy     创建者
     * @param enableReturn 是否允许退回
     * @return void
     */
    @Override
    public void addNodeTodo(
            ApprovalFlowPojo flow,
            ApprovalConfigPojo node,
            BenchmarkingReportPojo report,
            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(report.getId());
            todoTask.setModelName(report.getProjectName() + "对标报告");
            todoTask.setProcessTitle(flow.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(1);
            todoTask.setOwnerId(person);
            todoTask.setCurrentProcessor(node.getAssignees());
            list.add(todoTask);
        }

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

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

    /**
     * 取消流程
     * 取消当前审批流程
     *
     * @param flow   审批流程POJO
     * @param node   审批节点
     * @param status 状态
     * @param userId 用户ID
     * @return void
     */
    @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);
        // 更新报告状态
        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", flow.getTemplateId())
                .doQueryFirst(BenchmarkingReportPojo.class);
        report.setStatus(status);
        bd.getBusinessDatabase()
                .rowid("id", report.getRowId())
                .update("status", "DRAFT")
                .update("return_num", report.getReturnNum() + 1)
                .doUpdate(BenchmarkingReportPojo.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(report.getId());
            todoTask.setModelName(report.getTitle());
            todoTask.setProcessTitle(flow.getProcessTitle());
            todoTask.setStatusCode(flow.getFlowStatus());
            todoTask.setVersionNumber(0);
            todoTask.setOwnerId(flow.getCreateBy());
            todoTask.setCurrentProcessor(JSON.toJSONString(Collections.singletonList(flow.getCreateBy())));
            bd.getBusinessDatabase().doInsert(todoTask);
        }
        myself.updateTasks(flow, "编制", 0, node);
    }

    @Override
    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
    public ApprovalNodesDTO getApprovalUsers(String flowId) {
        ApprovalNodesDTO nodes = new ApprovalNodesDTO();
        nodes.setProcessTitle("");
        nodes.setExplanation("");
        List<ApprovalUserNodeDTO> list = new ArrayList<>();

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

        // 获取流程节点
        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
    public BenchmarkingReportPojo getReportDetail(String reportId) {
        BenchmarkingReportPojo benchmarkingReportPojo = bd.getBusinessDatabase()
                .viewQueryMode(true)
                .view("getReportById")
                .setVar("reportId", reportId)
                .doQueryFirst(BenchmarkingReportPojo.class);
        XdapUsers user = bd.getSystemDatabase()
                .eq("id", benchmarkingReportPojo.getCreateBy())
                .doQueryFirst(XdapUsers.class);
        if (user == null || user.getUsername() == null) {
            benchmarkingReportPojo.setCreateBy("未知用户-" + benchmarkingReportPojo.getCreateBy());
        } else {
            benchmarkingReportPojo.setCreateBy(user.getUsername());
        }
        return benchmarkingReportPojo;
    }

    @Override
    public ApprovalFlowNodeView getReportProcess(String flowId) {
        ApprovalFlowNodeView flowNodeView = new ApprovalFlowNodeView();
        ApprovalFlowPojo approvalFlow = bd.getBusinessDatabase()
                .eq("id", flowId)
                .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);

        BenchmarkingReportPojo report = bd.getBusinessDatabase()
                .eq("id", approvalFlow.getTemplateId())
                .doQueryFirst(BenchmarkingReportPojo.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(report.getTitle());
        flowNodeView.setTemplateVersion(1);
        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", flowId)
                .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(approvalRecordPojo -> {
                ApprovalConfigPojo approvalConfigPojo = nodesMap.get(approvalRecordPojo.getNode());
                if (approvalConfigPojo != null) {
                    flowNodes.add(getFlowNodeView(approvalConfigPojo, flowId, level));
                    nodeList.add(approvalConfigPojo.getNodeOrder());
                } else {
                    FlowNode flowNode = new FlowNode();
                    flowNode.setNode(approvalRecordPojo.getNode());
                    flowNode.setTodoUserName(approvalRecordPojo.getUserId());
                    flowNode.setResult(approvalRecordPojo.getResult());
                    flowNode.setApprovalTime(approvalRecordPojo.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, flowId, 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();
        ApprovalRecordPojo approvalRecordPojo = 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 (approvalRecordPojo != null) {
            // 节点已完成
            nodeView.setResult(approvalRecordPojo.getResult());
            nodeView.setOpinions(Collections.singletonList(getUserNames(Collections.singletonList(approvalRecordPojo.getUserId())) + ":" + approvalRecordPojo.getOpinion()));
            nodeView.setApprovalTime(approvalRecordPojo.getApprovalTime());
            nodeView.setTodoUserName(getUserNames(Collections.singletonList(approvalRecordPojo.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();
    }
}
