import type { FlowNode, FlowEdge } from '@/pages/Workflow/Design/types';
import { isConfigurableNode } from '@/pages/Workflow/Design/nodes/types';

/**
 * 节点变量定义
 */
export interface NodeVariable {
    nodeId: string;           // 节点UUID
    nodeName: string;         // 节点显示名称
    fieldName: string;        // 字段名
    fieldType: string;        // 字段类型
    displayText: string;      // 界面显示格式: ${节点名称.字段名}
    fullText: string;         // 完整文本格式: 节点名称.字段名（用于搜索）
}

/**
 * 获取当前节点的所有前序节点（通过DFS反向遍历）
 * 
 * 算法说明：
 * 1. 从当前节点开始，找到所有指向它的边（incoming edges）
 * 2. 通过这些边找到源节点，递归向上遍历
 * 3. 使用 visited 集合避免重复遍历（处理循环依赖）
 * 4. 过滤掉 START_EVENT 节点（它没有输出变量）
 * 
 * @param currentNodeId 当前节点ID（UUID）
 * @param allNodes 所有节点列表
 * @param allEdges 所有连接边列表
 * @returns 所有前序节点（不包括START节点）
 * 
 * @example
 * // 工作流：开始 -> Jenkins -> 通知 -> 结束
 * getAllPrecedingNodes("通知节点ID", allNodes, allEdges)
 * // => [Jenkins节点] （不包含开始节点）
 */
export const getAllPrecedingNodes = (
    currentNodeId: string,
    allNodes: FlowNode[],
    allEdges: FlowEdge[]
): FlowNode[] => {
    const precedingNodeIds = new Set<string>();
    const visited = new Set<string>();
    
    // DFS 反向遍历
    const dfs = (nodeId: string) => {
        if (visited.has(nodeId)) return;
        visited.add(nodeId);
        
        // 找到所有指向当前节点的边
        const incomingEdges = allEdges.filter(e => e.target === nodeId);
        
        incomingEdges.forEach(edge => {
            precedingNodeIds.add(edge.source);
            dfs(edge.source); // 递归向上遍历
        });
    };
    
    dfs(currentNodeId);
    
    // 返回节点对象，排除START节点（它没有输出）
    return allNodes.filter(node => 
        precedingNodeIds.has(node.id) && 
        node.data?.nodeType !== 'START_EVENT'
    );
};

/**
 * 收集指定节点的所有可用变量（来自前序节点的输出）
 * 
 * @param currentNodeId 当前节点ID
 * @param allNodes 所有节点列表
 * @param allEdges 所有连接边列表
 * @returns 变量列表
 */
export const collectNodeVariables = (
    currentNodeId: string,
    allNodes: FlowNode[],
    allEdges: FlowEdge[]
): NodeVariable[] => {
    const variables: NodeVariable[] = [];
    
    // 获取所有前序节点
    const precedingNodes = getAllPrecedingNodes(currentNodeId, allNodes, allEdges);
    
    // 遍历前序节点，提取输出字段
    precedingNodes.forEach(node => {
        const nodeDefinition = node.data?.nodeDefinition;
        
        // 检查节点是否有输出定义
        if (!nodeDefinition || !isConfigurableNode(nodeDefinition) || !nodeDefinition.outputs) {
            return;
        }
        
        // 获取节点显示名称（优先使用用户自定义的label）
        const nodeName = node.data.label || nodeDefinition.nodeName || 'Unknown';
        
        // 为每个输出字段创建变量
        nodeDefinition.outputs.forEach(output => {
            variables.push({
                nodeId: node.id,
                nodeName: nodeName,
                fieldName: output.name,
                fieldType: output.type,
                displayText: `\${${nodeName}.${output.name}}`,
                fullText: `${nodeName}.${output.name}`,
            });
        });
    });
    
    return variables;
};

/**
 * 按节点分组变量
 * 
 * @param variables 变量列表
 * @returns 分组后的变量 Map<节点名称, 变量列表>
 */
export const groupVariablesByNode = (variables: NodeVariable[]): Map<string, NodeVariable[]> => {
    const groups = new Map<string, NodeVariable[]>();
    
    variables.forEach(variable => {
        const key = variable.nodeName;
        if (!groups.has(key)) {
            groups.set(key, []);
        }
        groups.get(key)!.push(variable);
    });
    
    return groups;
};

