package com.qqchen.deploy.backend.workflow.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.qqchen.deploy.backend.workflow.constants.WorkFlowConstants;
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraphEdge;
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraph;
import com.qqchen.deploy.backend.workflow.dto.definition.workflow.WorkflowDefinitionGraphNode;
import com.qqchen.deploy.backend.workflow.enums.GatewayTypeEnums;
import com.qqchen.deploy.backend.workflow.enums.NodeTypeEnums;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.BpmnAutoLayout;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * BPMN 模型转换工具
 *
 * @author cascade
 * @date 2024-12-11
 */
@Slf4j
@Component
public class BpmnConverter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 将工作流定义图转换为Flowable XML
     *
     * @param graph      工作流定义图
     * @param processKey 流程定义的唯一标识
     * @return Flowable XML字符串
     * @throws RuntimeException 当转换失败时抛出
     */
    public String convertToXml(WorkflowDefinitionGraph graph, String processKey) {
        try {
            log.debug("开始转换工作流定义为XML, processKey: {}", processKey);

            // 步骤1：创建和初始化BPMN模型
            BpmnModel bpmnModel = new BpmnModel();
            Process process = createAndInitializeBpmnModel(processKey, bpmnModel);

            // 步骤2：转换所有节点
            Map<String, String> idMapping = convertNodes(graph.getNodes(), process);

            // 步骤3：转换连线
            convertEdgesToSequenceFlows(graph.getEdges(), idMapping, process);

            // 步骤4：自动布局
            new BpmnAutoLayout(bpmnModel).execute();

            // 转换为XML
            BpmnXMLConverter converter = new BpmnXMLConverter();
            byte[] bytes = converter.convertToXML(bpmnModel);
            String xml = new String(bytes, StandardCharsets.UTF_8);

            log.debug("工作流定义转换完成");
            return xml;

        } catch (Exception e) {
            log.error("转换工作流��义为XML失败", e);
            throw new RuntimeException("转换工作流定义为XML失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建并初始化BPMN模型
     *
     * @param processKey 流程定义的唯一标识
     * @param bpmnModel  BPMN模型对象
     * @return 初始化后的Process对象
     */
    private Process createAndInitializeBpmnModel(String processKey, BpmnModel bpmnModel) {
        // 步骤1.1：设置BPMN模型的基本属性
        bpmnModel.setTargetNamespace("http://www.flowable.org/test");
        bpmnModel.addError(WorkFlowConstants.WORKFLOW_EXEC_ERROR, WorkFlowConstants.WORKFLOW_EXEC_ERROR);

        // 步骤1.2：创建并配置Process对象
        Process process = new Process();
        // 确保processKey符合NCName规则
        String validProcessKey = processKey.replaceAll("[^a-zA-Z0-9-_.]", "_");
        process.setId(validProcessKey);
        process.setName(processKey); // 保持原始processKey作为显示名称
        process.setExecutable(true);

        // 步骤1.3：将Process添加到BPMN模型中
        bpmnModel.addProcess(process);

        return process;
    }

    /**
     * 转换工作流节点为BPMN节点
     *
     * @param nodes   工作流定义节点列表
     * @param process 流程定义对象
     * @return 节点ID映射关系
     */
    private Map<String, String> convertNodes(List<WorkflowDefinitionGraphNode> nodes, Process process) {
        // 步骤2.1：创建节点ID映射
        Map<String, String> idMapping = new HashMap<>();

        // 步骤2.2：遍历并转换每个节点
        for (WorkflowDefinitionGraphNode node : nodes) {
            log.debug("转换节点: {}, 类型: {}", node.getNodeName(), node.getNodeCode());
            convertSingleNode(node, process, idMapping);
        }

        return idMapping;
    }

    /**
     * 转换单个工作流节点为BPMN节点
     *
     * @param node      工作流节点定义
     * @param process   流程定义对象
     * @param idMapping 节点ID映射关系
     */
    private void convertSingleNode(WorkflowDefinitionGraphNode node, Process process, Map<String, String> idMapping) {
        try {
            String validId = sanitizeId(node.getId());
            idMapping.put(node.getId(), validId);
            
            FlowElement element;
            
            // ✅ 步骤2.3：检查是否为审批节点，特殊处理
            if ("APPROVAL".equals(node.getNodeCode())) {
                // 创建 UserTask 而不是 ServiceTask
                element = createUserTask(node, validId);
            } else {
                // 其他节点按原有逻辑处理
                @SuppressWarnings("unchecked")
                Class<? extends FlowElement> instanceClass = (Class<? extends FlowElement>) NodeTypeEnums.valueOf(node.getNodeCode())
                    .getBpmnType()
                    .getInstance();

                // 步骤2.4：创建节点实例并设置基本属性
                element = instanceClass.getDeclaredConstructor().newInstance();

                // 如果是网关节点，需要特殊处理
                if (element instanceof Gateway) {
                    element = createGatewayElement(node, validId);
                } else {
                    element.setId(validId);
                    element.setName(node.getNodeName());
                }
            }

            // 步骤2.5：配置节点的特定属性（传递原始节点ID和sanitized ID）
            configureFlowElement(element, node, process, validId);

            // 步骤2.6：将节点添加到流程中
            process.addFlowElement(element);
        } catch (Exception e) {
            log.error("节点转换失败: {}", node.getNodeName(), e);
            throw new RuntimeException("节点转换失败: " + e.getMessage(), e);
        }
    }

    /**
     * 直接使用前端生成的节点 ID
     * 前端已经生成了符合 NCName 规范的 ID（如 sid_265bc83e_9e7f_4acf_bd25_cf04c868a5da）
     *
     * @param id 前端生成的节点 ID
     * @return 节点 ID（直接返回）
     */
    private String sanitizeId(String id) {
        return id;
    }

    /**
     * 配置流程节点的特定属性
     *
     * @param element 流程节点元素
     * @param node    工作流节点定义
     * @param process 当前流程
     * @param validId sanitized 后的节点 ID
     */
    private void configureFlowElement(FlowElement element, WorkflowDefinitionGraphNode node, Process process, String validId) {
        // 步骤1：配置执行监听器
        Map<String, List<ExtensionElement>> extensionElements = configureExecutionListeners(element);

        // 步骤2：根据节点类型进行特定配置
        if (element instanceof UserTask) {
            // ✅ 审批节点（UserTask）的特殊配置
            configureUserTask((UserTask) element, node, extensionElements, validId);
        } else if (element instanceof ServiceTask) {
            configureServiceTask((ServiceTask) element, node, process, extensionElements, validId);
        } else {
            element.setExtensionElements(extensionElements);
        }
    }

    /**
     * 配置节点的执行监听器
     *
     * @param element 流程节点元素
     * @return 配置好的扩展元素Map
     */
    private Map<String, List<ExtensionElement>> configureExecutionListeners(FlowElement element) {
        Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
        List<ExtensionElement> executionListeners = new ArrayList<>();

        if (element instanceof Gateway) {
            // 网关节点只添加 start 监听器
            executionListeners.add(createExecutionListener("start", "${gatewayExecutionListener}"));
        } else {
            // 其他节点添加 start 和 end 监听器
            executionListeners.add(createExecutionListener("start", "${globalNodeExecutionListener}"));
            executionListeners.add(createExecutionListener("end", "${globalNodeExecutionListener}"));
        }

        extensionElements.put("executionListener", executionListeners);
        return extensionElements;
    }

    /**
     * 创��基本的扩展元素（包含执行监听器）
     *
     * @return 包含基本扩展元素的Map
     */
    private Map<String, List<ExtensionElement>> createBaseExtensionElements() {
        Map<String, List<ExtensionElement>> extensionElements = new HashMap<>();
        List<ExtensionElement> executionListeners = new ArrayList<>();

        // 添加开始事件监听器
        ExtensionElement startListener = createExecutionListener("start", "${globalNodeExecutionListener}");
        executionListeners.add(startListener);

        // 添加结束事件监听器
        ExtensionElement endListener = createExecutionListener("end", "${globalNodeExecutionListener}");
        executionListeners.add(endListener);

        extensionElements.put("executionListener", executionListeners);
        return extensionElements;
    }

    /**
     * 创建审批节点（UserTask）
     *
     * @param node    工作流节点定义
     * @param validId sanitized 后的节点 ID
     * @return UserTask 实例
     */
    private UserTask createUserTask(WorkflowDefinitionGraphNode node, String validId) {
        UserTask userTask = new UserTask();
        userTask.setId(validId);
        userTask.setName(node.getNodeName());
        
        // ⚠️ 不在这里设置 assignee，而是在 TaskListener 中动态设置
        // TaskListener 会解析 inputMapping 并直接调用 task.setAssignee()
        
        return userTask;
    }

    /**
     * 配置审批节点（UserTask）
     *
     * @param userTask          审批任务节点
     * @param node              工作流节点定义
     * @param extensionElements 扩展元素
     * @param validId           sanitized 后的节点 ID
     */
    private void configureUserTask(UserTask userTask, WorkflowDefinitionGraphNode node, Map<String, List<ExtensionElement>> extensionElements, String validId) {
        try {
            // ✅ 1. 创建 TaskListener（在任务创建时调用 ApprovalTaskListener）
            ExtensionElement taskListener = new ExtensionElement();
            taskListener.setName("taskListener");
            taskListener.setNamespace("http://flowable.org/bpmn");
            taskListener.setNamespacePrefix("flowable");
            taskListener.addAttribute(createAttribute("event", "create"));
            taskListener.addAttribute(createAttribute("delegateExpression", "${approvalTaskListener}"));
            
            // ✅ 2. 将 field 字段作为 TaskListener 的子元素添加（而不是 UserTask 的子元素）
            // 这样 ApprovalTaskListener 才能通过 @field 注解注入这些字段
            addFieldsToTaskListener(taskListener, node, validId);
            
            // ✅ 3. 将 TaskListener 添加到扩展元素
            extensionElements.computeIfAbsent("taskListener", k -> new ArrayList<>()).add(taskListener);
            
            // ✅ 4. 添加 ApprovalExecutionListener（在任务结束时构建 ApprovalOutputs）
            // 确保它在 globalNodeExecutionListener 之前执行，这样状态变量才能正确设置
            addApprovalExecutionListener(extensionElements);
            
            // ✅ 5. 设置扩展元素
            userTask.setExtensionElements(extensionElements);
            
            log.debug("配置审批节点完成: {}", node.getNodeName());
        } catch (Exception e) {
            log.error("配置审批节点失败: {}", node.getNodeName(), e);
            throw new RuntimeException("配置审批节点失败: " + e.getMessage(), e);
        }
    }

    /**
     * 向 TaskListener 添加 field 子元素
     *
     * @param taskListener TaskListener 扩展元素
     * @param node         工作流节点定义
     * @param validId      sanitized 后的节点 ID
     */
    private void addFieldsToTaskListener(ExtensionElement taskListener, WorkflowDefinitionGraphNode node, String validId) {
        try {
            // ✅ 1. 添加 nodeId field
            taskListener.addChildElement(createFieldElement("nodeId", validId));

            // ✅ 2. 添加 configs field
            if (node.getConfigs() != null) {
                String configsJson = objectMapper.writeValueAsString(node.getConfigs());
                taskListener.addChildElement(createFieldElement("configs", configsJson));
            }

            // ✅ 3. 添加 inputMapping field
            if (node.getInputMapping() != null) {
                String inputMappingJson = objectMapper.writeValueAsString(node.getInputMapping());
                taskListener.addChildElement(createFieldElement("inputMapping", inputMappingJson));
            }
        } catch (Exception e) {
            log.error("添加 TaskListener field 字段失败: {}", node.getNodeName(), e);
            throw new RuntimeException("添加 TaskListener field 字段失败: " + e.getMessage(), e);
        }
    }

    /**
     * 添加 ApprovalExecutionListener（审批任务结束监听器）
     * 确保它在 globalNodeExecutionListener 之前执行
     *
     * @param extensionElements 扩展元素
     */
    private void addApprovalExecutionListener(Map<String, List<ExtensionElement>> extensionElements) {
        List<ExtensionElement> executionListeners = 
            extensionElements.computeIfAbsent("executionListener", k -> new ArrayList<>());
        
        // 找到 end 事件的 globalNodeExecutionListener 的位置
        int endListenerIndex = -1;
        for (int i = 0; i < executionListeners.size(); i++) {
            ExtensionElement listener = executionListeners.get(i);
            String event = listener.getAttributeValue(null, "event");
            String delegateExpr = listener.getAttributeValue(null, "delegateExpression");
            
            if ("end".equals(event) && "${globalNodeExecutionListener}".equals(delegateExpr)) {
                endListenerIndex = i;
                break;
            }
        }
        
        // 在 globalNodeExecutionListener 之前插入 approvalExecutionListener
        // 这样审批结果会先被构建，状态变量也会被设置
        ExtensionElement approvalListener = createExecutionListener("end", "${approvalExecutionListener}");
        
        if (endListenerIndex >= 0) {
            executionListeners.add(endListenerIndex, approvalListener);
        } else {
            // 如果没有找到 globalNodeExecutionListener，直接添加到列表末尾
            executionListeners.add(approvalListener);
        }
        
        log.debug("Added ApprovalExecutionListener before GlobalNodeExecutionListener");
    }

    /**
     * 配置服务任务节点
     *
     * @param serviceTask       服务任务节点
     * @param node              工作流节点定义
     * @param process           当前流程
     * @param extensionElements 扩展元素
     * @param validId           sanitized 后的节点 ID
     */
    private void configureServiceTask(ServiceTask serviceTask, WorkflowDefinitionGraphNode node, Process process, Map<String, List<ExtensionElement>> extensionElements, String validId) {
        // ✅ 设置 delegateExpression（根据节点类型映射）
        String delegateExpression = getDelegateExpression(node.getNodeCode());
        if (delegateExpression != null && !delegateExpression.isEmpty()) {
            serviceTask.setImplementationType("delegateExpression");
            serviceTask.setImplementation(delegateExpression);
        }

        // ✅ 添加 field 字段（nodeId, configs, inputMapping）
        addExecutionVariables(extensionElements, node, validId);
        
        // ✅ 添加重试策略
        addRetryStrategy(extensionElements);
        
        serviceTask.setExtensionElements(extensionElements);
        addErrorBoundaryEventHandler(process, serviceTask);
    }

    /**
     * 根据节点类型获取对应的 delegateExpression
     *
     * @param nodeCode 节点类型编码
     * @return delegateExpression 字符串
     */
    private String getDelegateExpression(String nodeCode) {
        switch (nodeCode) {
            case "JENKINS_BUILD":
                return "${jenkinsBuildDelegate}";
            case "NOTIFICATION":
                return "${notificationDelegate}";
            case "SCRIPT_NODE":
                return "${shellDelegate}";
            case "APPROVAL":
            case "APPROVAL_NODE":
                return "${approvalDelegate}";
            case "DEPLOY_NODE":
                return "${deployDelegate}";
            default:
                log.warn("未知的节点类型: {}, 将不设置 delegateExpression", nodeCode);
                return null;
        }
    }

    /**
     * 创建扩展属性
     *
     * @param name  属性名
     * @param value 属性值
     * @return 扩展属性
     */
    private ExtensionAttribute createAttribute(String name, String value) {
        ExtensionAttribute attribute = new ExtensionAttribute();
        attribute.setName(name);
        attribute.setValue(value);
        return attribute;
    }

    /**
     * 添加执行实例级变量（field 字段）
     *
     * @param extensionElements 扩展元素
     * @param node              工作流节点定义
     * @param validId           sanitized 后的节点 ID
     */
    private void addExecutionVariables(Map<String, List<ExtensionElement>> extensionElements, WorkflowDefinitionGraphNode node, String validId) {
        try {
            // ✅ 1. 添加 nodeId field
            extensionElements.computeIfAbsent("field", k -> new ArrayList<>())
                .add(createFieldElement("nodeId", validId));

            // ✅ 2. 添加 configs field
            if (node.getConfigs() != null) {
                String configsJson = objectMapper.writeValueAsString(node.getConfigs());
                extensionElements.computeIfAbsent("field", k -> new ArrayList<>())
                    .add(createFieldElement("configs", configsJson));
            }

            // ✅ 3. 添加 inputMapping field
            if (node.getInputMapping() != null) {
                String inputMappingJson = objectMapper.writeValueAsString(node.getInputMapping());
                extensionElements.computeIfAbsent("field", k -> new ArrayList<>())
                    .add(createFieldElement("inputMapping", inputMappingJson));
            }
        } catch (Exception e) {
            log.error("添加执行变量失败: {}", node.getNodeName(), e);
            throw new RuntimeException("添加执行变量失败: " + e.getMessage(), e);
        }
    }

    /**
     * 创建 field 扩展元素
     *
     * @param fieldName  字段名
     * @param fieldValue 字段值
     * @return field 扩展元素
     */
    private ExtensionElement createFieldElement(String fieldName, String fieldValue) {
        // 创建 field 元素
        ExtensionElement fieldElement = new ExtensionElement();
        fieldElement.setName("field");
        fieldElement.setNamespace("http://flowable.org/bpmn");
        fieldElement.setNamespacePrefix("flowable");

        // 设置 field 的 name 属性
        Map<String, List<ExtensionAttribute>> fieldAttributes = new HashMap<>();
        fieldAttributes.put("name", Collections.singletonList(createAttribute("name", fieldName)));
        fieldElement.setAttributes(fieldAttributes);

        // 创建 string 子元素
        ExtensionElement stringElement = new ExtensionElement();
        stringElement.setName("string");
        stringElement.setNamespace("http://flowable.org/bpmn");
        stringElement.setNamespacePrefix("flowable");
        stringElement.setElementText(fieldValue);

        // 添加 string 子元素到 field
        fieldElement.addChildElement(stringElement);

        return fieldElement;
    }

    /**
     * 添加重试策略配置
     *
     * @param extensionElements 扩展元素
     */
    private void addRetryStrategy(Map<String, List<ExtensionElement>> extensionElements) {
        ExtensionElement retryConfig = new ExtensionElement();
        retryConfig.setName("failedJobRetryTimeCycle");
        retryConfig.setNamespace("http://flowable.org/bpmn");
        retryConfig.setNamespacePrefix("flowable");
        retryConfig.setElementText("R0/PT1H");  // 设置为0次重试

        List<ExtensionElement> retryElements = new ArrayList<>();
        retryElements.add(retryConfig);
        extensionElements.put("failedJobRetryTimeCycle", retryElements);
    }

    /**
     * 创建执行监听器扩展元素
     *
     * @param event              事件类型（start/end）
     * @param delegateExpression 委托表达式
     * @return 配置好的监听器扩展元素
     */
    private ExtensionElement createExecutionListener(String event, String delegateExpression) {
        ExtensionElement listener = new ExtensionElement();
        listener.setName("executionListener");
        listener.setNamespace("http://flowable.org/bpmn");
        listener.setNamespacePrefix("flowable");

        // 设置事件属性
        ExtensionAttribute eventAttr = new ExtensionAttribute();
        eventAttr.setName("event");
        eventAttr.setValue(event);

        // 设置委托表达式属性
        ExtensionAttribute delegateAttr = new ExtensionAttribute();
        delegateAttr.setName("delegateExpression");
        delegateAttr.setValue(delegateExpression);

        // 添加属性到监听器
        Map<String, List<ExtensionAttribute>> attributes = new HashMap<>();
        attributes.put("event", Collections.singletonList(eventAttr));
        attributes.put("delegateExpression", Collections.singletonList(delegateAttr));
        listener.setAttributes(attributes);

        return listener;
    }

    /**
     * 为活动节点添加错误边界事件和错误结束事件
     * 当节点执行失败时，会触发错误边界事件，并流转到错误结束事件
     *
     * @param process  BPMN流程定义
     * @param activity 需要添加错误处理的活动节点
     */
    private void addErrorBoundaryEventHandler(Process process, Activity activity) {
        BoundaryEvent boundaryEvent = createErrorBoundaryEvent(activity);
        EndEvent errorEndEvent = createErrorEndEvent(activity);
        SequenceFlow errorFlow = createErrorSequenceFlow(boundaryEvent, errorEndEvent);

        process.addFlowElement(boundaryEvent);
        process.addFlowElement(errorEndEvent);
        process.addFlowElement(errorFlow);
    }

    /**
     * 创建错误边界事件
     *
     * @param activity 关联的活动节点
     * @return 配置好的错误边界事件
     */
    private BoundaryEvent createErrorBoundaryEvent(Activity activity) {
        BoundaryEvent boundaryEvent = new BoundaryEvent();
        boundaryEvent.setId(WorkFlowConstants.BOUNDARY_EVENT_ERROR_PREFIX + activity.getId());
        boundaryEvent.setName("边界事件异常");
        boundaryEvent.setAttachedToRef(activity);
        boundaryEvent.setAttachedToRefId(activity.getId());
        boundaryEvent.setCancelActivity(true);  // 确保取消原有活动

        // 配置错误事件定义
        ErrorEventDefinition errorEventDefinition = new ErrorEventDefinition();
        errorEventDefinition.setErrorCode(WorkFlowConstants.WORKFLOW_EXEC_ERROR);
        boundaryEvent.addEventDefinition(errorEventDefinition);

        return boundaryEvent;
    }

    /**
     * 创建错误结束事件
     *
     * @param activity 关联的活动节点
     * @return 配置好的错误结束事件
     */
    private EndEvent createErrorEndEvent(Activity activity) {
        EndEvent errorEndEvent = new EndEvent();
        errorEndEvent.setId(WorkFlowConstants.END_EVENT_ERROR_PREFIX + activity.getId());
        errorEndEvent.setName("结束事件异常");
        // 添加终止定义
        TerminateEventDefinition terminateEventDefinition = new TerminateEventDefinition();
        errorEndEvent.addEventDefinition(terminateEventDefinition);

//        ErrorEventDefinition errorEventDefinition = new ErrorEventDefinition();
//        errorEventDefinition.setErrorCode(WorkFlowConstants.WORKFLOW_EXEC_ERROR);
//        errorEndEvent.addEventDefinition(errorEventDefinition);

        return errorEndEvent;
    }

    /**
     * 创建错误处理流程的连线
     *
     * @param boundaryEvent 错误边界事件
     * @param errorEndEvent 错误结束事件
     * @return 配置好的连线
     */
    private SequenceFlow createErrorSequenceFlow(BoundaryEvent boundaryEvent, EndEvent errorEndEvent) {
        SequenceFlow errorFlow = new SequenceFlow();
        errorFlow.setId(WorkFlowConstants.SEQUENCE_FLOW_ERROR_PREFIX + boundaryEvent.getAttachedToRefId());
        errorFlow.setName("连接线异常");
        errorFlow.setSourceRef(boundaryEvent.getId());
        errorFlow.setTargetRef(errorEndEvent.getId());

        return errorFlow;
    }

    /**
     * 创建网关节点
     *
     * @param node    工作流节点定义
     * @param validId 有效的节点ID
     * @return 创建的网关节点
     */
    private Gateway createGatewayElement(WorkflowDefinitionGraphNode node, String validId) {
//        if (node.getPanelVariables() == null) {
//            throw new IllegalArgumentException("Gateway node must have panel variables");
//        }
//
//        String gatewayTypeCode = node.getPanelVariables().get("gatewayType").asText();
//        GatewayTypeEnums gatewayType = GatewayTypeEnums.fromCode(gatewayTypeCode);
//
//        Gateway gateway;
//        switch (gatewayType) {
//            case EXCLUSIVE_GATEWAY:
//                gateway = new ExclusiveGateway();
//                break;
//            case PARALLEL_GATEWAY:
//                gateway = new ParallelGateway();
//                break;
//            case INCLUSIVE_GATEWAY:
//                gateway = new InclusiveGateway();
//                break;
//            default:
//                throw new IllegalArgumentException("Unsupported gateway type: " + gatewayType);
//        }
//
//        gateway.setId(validId);
//        gateway.setName(node.getNodeName());
//
//        return gateway;
        return null;
    }

    /**
     * 转换连线为顺序流
     *
     * @param edges     工作流定义边集合
     * @param idMapping 节点ID映射
     * @param process   流程定义
     */
    private void convertEdgesToSequenceFlows(List<WorkflowDefinitionGraphEdge> edges, Map<String, String> idMapping, Process process) {
        for (WorkflowDefinitionGraphEdge edge : edges) {
            log.debug("转换连线: from {} to {}", edge.getFrom(), edge.getTo());

            SequenceFlow flow = new SequenceFlow();
            // ✅ 直接使用前端生成的 edge ID（前端已经生成了 eid_ 开头的 ID）
            flow.setId(edge.getId());
            flow.setName(edge.getName());
            flow.setSourceRef(idMapping.get(edge.getFrom()));
            flow.setTargetRef(idMapping.get(edge.getTo()));

            // 处理条件
            if (edge.getConfig() != null && edge.getConfig().getCondition() != null) {
                if ("EXPRESSION".equals(edge.getConfig().getCondition().getType())) {
                    String expression = edge.getConfig().getCondition().getExpression();
                    flow.setConditionExpression(expression);
                }
            }

            process.addFlowElement(flow);
        }
    }
}
