"""
子流程节点
"""
import logging
import time
from typing import Any, Dict, List, Optional

from sqlalchemy import select

from ..base import BaseNode, NodeContext, NodeResult
from ..registry import NodeRegistry

logger = logging.getLogger(__name__)


@NodeRegistry.register
class SubflowNode(BaseNode):
    """
    子流程节点
    
    调用另一个工作流作为子流程执行
    """
    
    node_type = 'subflow'
    node_name = '子流程'
    node_category = 'flow_control'
    node_icon = 'workflow'
    node_description = '调用另一个工作流作为子流程'
    
    inputs = [
        {
            'name': 'input',
            'type': 'any',
            'description': '输入数据',
        },
    ]
    
    outputs = [
        {
            'name': 'subflow_result',
            'type': 'object',
            'description': '子流程执行结果',
        },
    ]
    
    def execute(self, context: NodeContext) -> NodeResult:
        """同步执行子流程（不推荐，建议使用异步版本）"""
        return NodeResult(
            success=False,
            error='子流程节点需要异步执行，请使用 execute_async 方法',
        )
    
    async def execute_async(self, context: NodeContext) -> NodeResult:
        """异步执行子流程"""
        try:
            # 获取配置
            subflow_id = self.config.get('subflow_id', '')
            if not subflow_id:
                return NodeResult(success=False, error='未配置子流程')
            
            # 解析变量引用
            subflow_id = context.resolve_template(subflow_id)
            
            var_pass_mode = self.config.get('var_pass_mode', 'all')
            result_pass_mode = self.config.get('result_pass_mode', 'all')
            result_variable = self.config.get('result_variable', 'subflow_result')
            max_depth = self.config.get('max_depth', 5)
            
            # 检查嵌套深度
            current_depth = context.metadata.get('subflow_depth', 0)
            if current_depth >= max_depth:
                return NodeResult(
                    success=False,
                    error=f'子流程嵌套深度超过限制 ({max_depth})',
                )
            
            # 加载子工作流
            subflow = await self._load_subflow(context.db_session, subflow_id)
            if not subflow:
                return NodeResult(success=False, error=f'子流程不存在: {subflow_id}')
            
            # 检查循环依赖
            parent_workflows = context.metadata.get('parent_workflows', [])
            if subflow_id in parent_workflows:
                return NodeResult(
                    success=False,
                    error=f'检测到循环依赖: 子流程 {subflow_id} 已在调用链中',
                )
            
            # 准备子流程输入变量
            subflow_inputs = self._prepare_inputs(context, var_pass_mode)
            
            # 检查是否有恢复状态（从等待中恢复）
            subflow_state = context.metadata.pop('_subflow_state', None)
            
            # 执行子流程
            start_time = time.time()
            if subflow_state:
                # 从等待状态恢复执行
                logger.info(f'[子流程] 从等待状态恢复执行，当前节点: {subflow_state.get("current_node_id")}')
                subflow_result = await self._resume_subflow(
                    subflow_state,
                    subflow_inputs,
                    context,
                    current_depth + 1,
                    parent_workflows + [subflow_id],
                )
            else:
                # 正常执行子流程
                subflow_result = await self._execute_subflow(
                    subflow, 
                    subflow_inputs, 
                    context,
                    current_depth + 1,
                    parent_workflows + [subflow_id],
                )
            elapsed_time = int((time.time() - start_time) * 1000)
            
            # 检查是否需要转发交互式节点
            forward_interactive = self.config.get('forward_interactive', False)
            if subflow_result.get('waiting_for_input') and forward_interactive:
                # 转发等待状态到主流程
                return self._forward_waiting_state(subflow_result, context, elapsed_time)
            elif subflow_result.get('waiting_for_input') and not forward_interactive:
                # 不转发交互式节点，报错
                waiting_node = subflow_result.get('logs', [{}])[-1].get('node_label', '未知')
                return NodeResult(
                    success=False,
                    error=f'子流程中的交互式节点 "{waiting_node}" 需要用户输入，但未开启"转发交互式节点"选项',
                    elapsed_time=elapsed_time,
                )
            
            # 处理结果
            return self._process_result(
                subflow_result, 
                context, 
                result_pass_mode, 
                result_variable,
                elapsed_time,
            )
            
        except Exception as e:
            logger.exception(f'子流程执行失败: {e}')
            return NodeResult(success=False, error=f'子流程执行失败: {str(e)}')
    
    async def _load_subflow(self, db_session, subflow_id: str):
        """加载子工作流"""
        if not db_session:
            return None
        
        from ai_platform.models import AIWorkflow
        
        result = await db_session.execute(
            select(AIWorkflow).where(
                AIWorkflow.id == subflow_id,
                AIWorkflow.is_deleted == False
            )
        )
        return result.scalar_one_or_none()
    
    def _prepare_inputs(self, context: NodeContext, mode: str) -> Dict[str, Any]:
        """准备子流程输入变量"""
        if mode == 'none':
            return {}
        elif mode == 'all':
            # 传递所有变量（排除内部变量）
            return {
                k: v for k, v in context.variables.items()
                if not k.startswith('_')
            }
        elif mode == 'selected':
            # 使用新的变量映射结构
            var_mappings = self.config.get('var_mappings', [])
            
            result = {}
            for mapping in var_mappings:
                name = mapping.get('name', '')  # 子流程中的变量名
                value = mapping.get('value', '')  # 主流程中的变量值（可能是模板）
                
                if not name:
                    continue
                
                # 解析变量值，保留原始数据类型
                resolved_value = self._resolve_variable_value(value, context)
                result[name] = resolved_value
            
            return result
        
        return {}
    
    def _resolve_variable_value(self, value: str, context: NodeContext) -> Any:
        """
        解析变量值，保留原始数据类型
        
        支持格式：
        - {{variable_name}} - 直接变量引用
        - {{NodeID.key}} - 节点输出引用
        """
        import re
        
        if not isinstance(value, str):
            return value
        
        value = value.strip()
        
        # 检查是否是纯变量引用 {{...}}
        if value.startswith('{{') and value.endswith('}}'):
            # 检查是否只有一个变量引用（没有其他文本）
            pattern = r'^\{\{([^}]+)\}\}$'
            match = re.match(pattern, value)
            if match:
                var_ref = match.group(1).strip()
                
                # 尝试解析 NodeID.key 格式
                if '.' in var_ref:
                    parts = var_ref.split('.', 1)
                    node_id = parts[0]
                    var_key = parts[1]
                    
                    # 先尝试从节点输出命名空间获取
                    node_outputs = context.variables.get(f'_node_{node_id}')
                    if isinstance(node_outputs, dict) and var_key in node_outputs:
                        return node_outputs[var_key]
                    
                    # 回退：尝试直接从变量获取
                    node_data = context.variables.get(node_id)
                    if isinstance(node_data, dict) and var_key in node_data:
                        return node_data[var_key]
                
                # 直接变量引用
                if var_ref in context.variables:
                    return context.variables[var_ref]
        
        # 如果包含变量引用但不是纯变量引用，使用 resolve_template（会转换为字符串）
        if '{{' in value and '}}' in value:
            return context.resolve_template(value)
        
        # 普通字符串值
        return value
    
    def _get_child_nodes(self, node_map: Dict[str, Any], parent_node_id: str) -> List[str]:
        """
        获取循环节点的子节点列表
        
        子节点通过 parentNode 属性关联到循环节点
        注意：parentNode 可能在节点顶层或 data 中
        """
        child_nodes = []
        for node_id, node_config in node_map.items():
            # 检查顶层 parentNode 属性（Vue Flow 标准格式）
            parent_node = node_config.get('parentNode')
            # 也检查 data 中的 parentNode（兼容其他格式）
            if not parent_node:
                parent_node = node_config.get('data', {}).get('parentNode')
            if parent_node == parent_node_id:
                child_nodes.append(node_id)
        return child_nodes
    
    async def _execute_loop_in_subflow(
        self,
        node_map: Dict[str, Any],
        edge_map: Dict[str, List[str]],
        parallel_edge_map: Dict[str, Dict[str, str]],
        loop_node_id: str,
        loop_config: Dict[str, Any],
        context: NodeContext,
        logs: List[Dict],
        subflow_id: str,
        resume_node_id: str = None,
    ) -> Dict[str, Any]:
        """
        在子流程中执行循环体
        
        Args:
            node_map: 节点映射
            edge_map: 边映射
            parallel_edge_map: 并行边映射
            loop_node_id: 循环节点 ID
            loop_config: 循环配置
            context: 执行上下文
            logs: 日志列表
            subflow_id: 子流程 ID
            resume_node_id: 恢复执行的节点 ID（用于从暂停状态恢复）
            
        Returns:
            循环执行结果
        """
        loop_mode = context.variables.get('_loop_mode', 'for_each')
        max_iterations = loop_config.get('max_iterations', 100)
        item_var_name = loop_config.get('item_variable_name', 'item')
        index_var_name = loop_config.get('index_variable_name', 'index')
        
        # 获取循环体子节点
        child_node_ids = self._get_child_nodes(node_map, loop_node_id)
        logger.info(f'[子流程循环] 通过 parentNode 获取子节点: {child_node_ids}')
        if not child_node_ids:
            child_node_ids = loop_config.get('childNodes', [])
            logger.info(f'[子流程循环] 通过 childNodes 配置获取子节点: {child_node_ids}')
        
        if not child_node_ids:
            logger.warning(f'[子流程循环] 循环节点 {loop_node_id} 没有子节点，node_map keys: {list(node_map.keys())}')
            return {'success': True, 'total_tokens': 0}
        
        # 构建子节点的边映射
        child_edge_map = {}
        for source_id in child_node_ids:
            targets = edge_map.get(source_id, [])
            child_targets = [t for t in targets if t in child_node_ids]
            if child_targets:
                child_edge_map[source_id] = child_targets
        
        # 找到循环体的起始节点
        nodes_with_incoming = set()
        for targets in child_edge_map.values():
            nodes_with_incoming.update(targets)
        
        start_nodes = [n for n in child_node_ids if n not in nodes_with_incoming]
        if not start_nodes:
            start_nodes = [child_node_ids[0]]
        
        loop_body_start_id = start_nodes[0]
        
        # 从当前循环索引开始
        iteration = context.variables.get('_loop_index', 0)
        total_tokens = 0
        
        logger.info(f'[子流程循环] 开始执行循环，mode={loop_mode}, max_iterations={max_iterations}, start_iteration={iteration}')
        logger.info(f'[子流程循环] child_node_ids={child_node_ids}, loop_body_start_id={loop_body_start_id}')
        logger.info(f'[子流程循环] child_edge_map={child_edge_map}')
        logger.info(f'[子流程循环] _loop_items={context.variables.get("_loop_items", [])}, _loop_index={context.variables.get("_loop_index")}')
        
        while iteration < max_iterations:
            # 检查是否继续循环
            if loop_mode == 'for_each':
                items = context.variables.get('_loop_items', [])
                current_index = context.variables.get('_loop_index', 0)
                logger.info(f'[子流程循环] 迭代 {iteration}: items 长度={len(items)}, current_index={current_index}')
                if current_index >= len(items):
                    logger.info(f'[子流程循环] 退出循环: current_index({current_index}) >= len(items)({len(items)})')
                    break
                # 设置当前循环项和索引
                current_item = items[current_index]
                context.variables[item_var_name] = current_item
                context.variables[index_var_name] = current_index
                context.variables['_current_item'] = current_item
                context.variables['_current_index'] = current_index
                context.variables[f'_node_{loop_node_id}'] = {
                    item_var_name: current_item,
                    index_var_name: current_index,
                    'total': len(items),
                }
            elif loop_mode == 'while':
                from ai_platform.nodes.builtin.loop_node import LoopNode
                loop_node_instance = LoopNode(loop_config)
                if not loop_node_instance._evaluate_condition(context):
                    break
                context.variables[index_var_name] = iteration
            
            # 执行循环体
            # 如果是恢复执行，从指定节点开始；否则从循环体起始节点开始
            current_id = resume_node_id if resume_node_id and resume_node_id in child_node_ids else loop_body_start_id
            iteration_output = None
            executed_nodes = set()
            
            # 如果是恢复执行，记录日志
            if resume_node_id and resume_node_id in child_node_ids:
                logger.info(f'[子流程循环] 从节点 {resume_node_id} 恢复执行（迭代 {iteration}）')
                # 恢复后只执行一次，然后清除 resume_node_id
                resume_node_id = None
            
            while current_id and current_id in child_node_ids:
                if current_id in executed_nodes:
                    break
                executed_nodes.add(current_id)
                
                node_config = node_map.get(current_id)
                if not node_config:
                    break
                
                node_type = node_config.get('type', '')
                node_label = node_config.get('data', {}).get('label', current_id)
                
                # 创建节点实例
                node_instance = NodeRegistry.create_instance(node_type, node_config.get('data', {}))
                if not node_instance:
                    next_nodes = child_edge_map.get(current_id, [])
                    current_id = next_nodes[0] if next_nodes else None
                    continue
                
                # 执行节点
                start_time = time.time()
                result = await node_instance.execute_async(context)
                elapsed = int((time.time() - start_time) * 1000)
                
                # 记录日志
                log_entry = {
                    'node_id': current_id,
                    'node_type': node_type,
                    'node_label': node_label,
                    'status': 'completed' if result.success else 'failed',
                    'output': result.output,
                    'error': result.error,
                    'elapsed_time': elapsed,
                    'tokens_used': result.tokens_used,
                    'loop_iteration': iteration,
                }
                if result.events:
                    log_entry['events'] = result.events
                logs.append(log_entry)
                
                total_tokens += result.tokens_used
                
                # 检查是否需要等待用户输入
                if result.waiting_for_input:
                    return {
                        'success': True,
                        'waiting_for_input': True,
                        'waiting_config': result.waiting_config,
                        'outputs': context.variables,
                        'logs': logs,
                        'total_tokens': total_tokens,
                        'subflow_state': {
                            'current_node_id': current_id,
                            'node_map': {k: v for k, v in node_map.items()},
                            'edge_map': edge_map,
                            'parallel_edge_map': parallel_edge_map,
                            'subflow_id': subflow_id,
                            'sent_message_nodes': [],
                            'loop_state': {
                                'loop_node_id': loop_node_id,
                                'iteration': iteration,
                                'current_index': context.variables.get('_loop_index', 0),
                            },
                        },
                    }
                
                if not result.success:
                    return {
                        'success': False,
                        'error': f'子流程循环节点 {node_label} 执行失败: {result.error}',
                        'outputs': context.variables,
                        'logs': logs,
                        'total_tokens': total_tokens,
                    }
                
                # 更新上下文
                context.variables.update(result.output_variables)
                context.previous_output = result.output
                iteration_output = result.output
                
                context.variables[f'_node_{current_id}'] = {
                    'output': result.output,
                    **result.output_variables,
                }
                
                # 下一个节点
                if result.next_node_id and result.next_node_id in child_node_ids:
                    current_id = result.next_node_id
                else:
                    next_nodes = child_edge_map.get(current_id, [])
                    current_id = next_nodes[0] if next_nodes else None
            
            # 收集本次迭代结果
            loop_results = context.variables.get('_loop_results', [])
            loop_results.append(iteration_output)
            context.variables['_loop_results'] = loop_results
            
            # 更新循环索引
            context.variables['_loop_index'] = context.variables.get('_loop_index', 0) + 1
            
            iteration += 1
        
        # 清理循环变量
        context.variables.pop('_loop_items', None)
        context.variables.pop('_loop_index', None)
        context.variables.pop('_loop_total', None)
        context.variables.pop('_loop_mode', None)
        context.variables.pop('_current_item', None)
        context.variables.pop('_current_index', None)
        
        return {'success': True, 'total_tokens': total_tokens}
    
    async def _execute_subflow(
        self,
        subflow,
        inputs: Dict[str, Any],
        parent_context: NodeContext,
        depth: int,
        parent_workflows: List[str],
    ) -> Dict[str, Any]:
        """执行子流程"""
        from ai_platform.nodes import NodeRegistry
        
        # 使用已发布版本，如果没有则使用草稿版本
        definition = subflow.published_definition or subflow.definition
        nodes = definition.get('nodes', [])
        edges = definition.get('edges', [])
        
        if not nodes:
            return {'success': False, 'error': '子流程没有节点', 'logs': []}
        
        # 构建节点映射和边映射
        node_map = {node['id']: node for node in nodes}
        edge_map = {}
        parallel_edge_map = {}
        
        for edge in edges:
            source = edge.get('source', '')
            target = edge.get('target', '')
            source_handle = edge.get('sourceHandle', '')
            if source not in edge_map:
                edge_map[source] = []
            edge_map[source].append(target)
            if source_handle:
                if source not in parallel_edge_map:
                    parallel_edge_map[source] = {}
                parallel_edge_map[source][source_handle] = target
        
        # 找到开始节点
        start_node = None
        for node in nodes:
            if node.get('type') == 'start':
                start_node = node
                break
        
        if not start_node:
            return {'success': False, 'error': '子流程没有开始节点', 'logs': []}
        
        # 创建子流程上下文
        subflow_context = NodeContext(
            workflow_run_id=f"{parent_context.workflow_run_id}_sub_{subflow.id}",
            variables=inputs.copy(),
            user_input=inputs.get('user_input', ''),
            user_id=parent_context.user_id,
            conversation_history=parent_context.conversation_history.copy(),
            db_session=parent_context.db_session,
            metadata={
                'subflow_depth': depth,
                'parent_workflows': parent_workflows,
                'parent_run_id': parent_context.workflow_run_id,
            },
        )
        
        # 执行节点序列
        logs = []
        total_tokens = 0
        current_node_id = start_node['id']
        
        while current_node_id:
            node_config = node_map.get(current_node_id)
            if not node_config:
                break
            
            node_type = node_config.get('type', '')
            node_label = node_config.get('data', {}).get('label', current_node_id)
            
            # 结束节点
            if node_type == 'end':
                node_instance = NodeRegistry.create_instance(node_type, node_config.get('data', {}))
                if node_instance:
                    result = node_instance.execute(subflow_context)
                    logs.append({
                        'node_id': current_node_id,
                        'node_type': node_type,
                        'node_label': node_label,
                        'status': 'completed',
                        'output': result.output,
                    })
                break
            
            # 创建并执行节点
            node_instance = NodeRegistry.create_instance(node_type, node_config.get('data', {}))
            if not node_instance:
                logger.warning(f'[子流程] 未知节点类型: {node_type}')
                next_nodes = edge_map.get(current_node_id, [])
                current_node_id = next_nodes[0] if next_nodes else None
                continue
            
            # 执行节点
            start_time = time.time()
            result = await node_instance.execute_async(subflow_context)
            elapsed = int((time.time() - start_time) * 1000)
            
            # 循环节点：执行循环体
            if node_type == 'loop':
                loop_node_id = current_node_id
                loop_config = node_config.get('data', {})
                
                # 记录循环节点初始化日志
                logs.append({
                    'node_id': current_node_id,
                    'node_type': node_type,
                    'node_label': node_label,
                    'status': 'completed' if result.success else 'failed',
                    'output': result.output,
                    'elapsed_time': elapsed,
                })
                
                if result.success:
                    # 更新上下文变量（循环节点会设置 _loop_items, _loop_index 等）
                    subflow_context.variables.update(result.output_variables)
                    logger.info(f'[子流程] 循环节点初始化完成，_loop_items 长度={len(subflow_context.variables.get("_loop_items", []))}, _loop_index={subflow_context.variables.get("_loop_index")}')
                    
                    # 执行循环体
                    loop_result = await self._execute_loop_in_subflow(
                        node_map, edge_map, parallel_edge_map, loop_node_id,
                        loop_config, subflow_context, logs, subflow.id
                    )
                    
                    total_tokens += loop_result.get('total_tokens', 0)
                    
                    # 检查循环是否因等待用户输入而暂停
                    if loop_result.get('waiting_for_input'):
                        return loop_result
                    
                    # 检查循环是否失败
                    if not loop_result.get('success', True):
                        return loop_result
                    
                    # 获取循环结果
                    loop_results = subflow_context.variables.get('_loop_results', [])
                    output_var = loop_config.get('output_variable', 'loop_results')
                    subflow_context.variables[output_var] = loop_results
                
                # 循环完成后从循环节点的输出边继续
                next_nodes = edge_map.get(loop_node_id, [])
                # 过滤掉子节点
                child_node_ids = self._get_child_nodes(node_map, loop_node_id)
                next_nodes = [n for n in next_nodes if n not in child_node_ids]
                current_node_id = next_nodes[0] if next_nodes else None
                continue
            
            # 检查是否需要等待用户输入（交互式节点）
            if result.waiting_for_input:
                # 记录等待状态的日志
                log_entry = {
                    'node_id': current_node_id,
                    'node_type': node_type,
                    'node_label': node_label,
                    'status': 'waiting',
                    'output': result.output,
                    'elapsed_time': elapsed,
                }
                logs.append(log_entry)
                
                # 返回等待状态，包含子流程执行状态以便恢复
                return {
                    'success': True,
                    'waiting_for_input': True,
                    'waiting_config': result.waiting_config,
                    'outputs': subflow_context.variables,
                    'logs': logs,
                    'total_tokens': total_tokens,
                    # 保存子流程状态以便恢复
                    'subflow_state': {
                        'current_node_id': current_node_id,
                        'node_map': {k: v for k, v in node_map.items()},
                        'edge_map': edge_map,
                        'parallel_edge_map': parallel_edge_map,
                        'subflow_id': subflow.id,
                        'sent_message_nodes': [],  # 初始化已发送消息节点列表
                    },
                }
            
            # 记录日志
            log_entry = {
                'node_id': current_node_id,
                'node_type': node_type,
                'node_label': node_label,
                'status': 'completed' if result.success else 'failed',
                'output': result.output,
                'error': result.error,
                'elapsed_time': elapsed,
                'tokens_used': result.tokens_used,
            }
            
            # 收集消息事件（用于转发到主流程）
            if result.events:
                log_entry['events'] = result.events
            
            logs.append(log_entry)
            
            total_tokens += result.tokens_used
            
            if not result.success:
                return {
                    'success': False,
                    'error': f'子流程节点 {node_label} 执行失败: {result.error}',
                    'outputs': subflow_context.variables,
                    'logs': logs,
                    'total_tokens': total_tokens,
                }
            
            # 更新上下文
            subflow_context.variables.update(result.output_variables)
            subflow_context.previous_output = result.output
            
            # 保存节点输出到命名空间
            subflow_context.variables[f'_node_{current_node_id}'] = {
                'output': result.output,
                **result.output_variables,
            }
            
            # 确定下一个节点
            if result.next_node_id:
                if result.next_node_id in parallel_edge_map.get(current_node_id, {}):
                    current_node_id = parallel_edge_map[current_node_id][result.next_node_id]
                elif result.next_node_id in node_map:
                    current_node_id = result.next_node_id
                else:
                    next_nodes = edge_map.get(current_node_id, [])
                    current_node_id = next_nodes[0] if next_nodes else None
            else:
                next_nodes = edge_map.get(current_node_id, [])
                current_node_id = next_nodes[0] if next_nodes else None
        
        return {
            'success': True,
            'outputs': subflow_context.variables,
            'logs': logs,
            'total_tokens': total_tokens,
        }
    
    def _process_result(
        self,
        subflow_result: Dict[str, Any],
        context: NodeContext,
        result_pass_mode: str,
        result_variable: str,
        elapsed_time: int,
    ) -> NodeResult:
        """处理子流程结果"""
        if not subflow_result.get('success'):
            return NodeResult(
                success=False,
                error=subflow_result.get('error', '子流程执行失败'),
                elapsed_time=elapsed_time,
            )
        
        output_vars = {}
        subflow_outputs = subflow_result.get('outputs', {})
        
        if result_pass_mode == 'all':
            # 传递所有输出变量（排除内部变量）
            output_vars = {
                k: v for k, v in subflow_outputs.items()
                if not k.startswith('_')
            }
        elif result_pass_mode == 'selected':
            # 传递选定的变量
            result_vars = self.config.get('result_vars', [])
            for var in result_vars:
                if var in subflow_outputs:
                    output_vars[var] = subflow_outputs[var]
        
        # 将完整结果存储到指定变量
        output_vars[result_variable] = {
            'success': True,
            'outputs': {k: v for k, v in subflow_outputs.items() if not k.startswith('_')},
            'logs': subflow_result.get('logs', []),
            'total_tokens': subflow_result.get('total_tokens', 0),
        }
        
        # 收集子流程的消息事件（如果配置了显示子流程消息）
        # 只收集尚未发送的消息（避免重复发送）
        events = []
        show_subflow_messages = self.config.get('show_subflow_messages', False)
        if show_subflow_messages:
            subflow_name = self.config.get('subflow_name', '子流程')
            # 获取已发送的消息节点ID列表（从子流程状态中）
            subflow_state = subflow_result.get('subflow_state', {})
            sent_message_nodes = subflow_state.get('sent_message_nodes', [])
            
            for log in subflow_result.get('logs', []):
                node_id = log.get('node_id')
                log_events = log.get('events', [])
                for event in log_events:
                    if event.get('type') == 'message':
                        # 只发送尚未发送过的消息
                        if node_id not in sent_message_nodes:
                            events.append({
                                'type': 'message',
                                'content': event.get('content', ''),
                                'message_type': event.get('message_type', 'text'),
                                'from_subflow': True,
                                'subflow_name': subflow_name,
                            })
        
        return NodeResult(
            success=True,
            output=f"子流程执行成功，共 {len(subflow_result.get('logs', []))} 个节点",
            output_variables=output_vars,
            tokens_used=subflow_result.get('total_tokens', 0),
            elapsed_time=elapsed_time,
            events=events if events else None,
        )
    
    def _forward_waiting_state(
        self,
        subflow_result: Dict[str, Any],
        context: NodeContext,
        elapsed_time: int,
    ) -> NodeResult:
        """转发子流程的等待状态到主流程"""
        subflow_name = self.config.get('subflow_name', '子流程')
        waiting_config = subflow_result.get('waiting_config', {})
        subflow_state = subflow_result.get('subflow_state', {})
        
        # 收集之前节点的消息事件（在等待节点之前的消息应该先显示）
        # 但只收集尚未发送的消息（避免重复发送）
        events = []
        show_subflow_messages = self.config.get('show_subflow_messages', False)
        # 获取已发送的消息节点ID列表（从子流程状态中），复制一份避免修改原始列表
        sent_message_nodes = list(subflow_state.get('sent_message_nodes', []))
        
        if show_subflow_messages:
            for log in subflow_result.get('logs', []):
                # 跳过当前等待节点的日志
                if log.get('status') == 'waiting':
                    continue
                
                node_id = log.get('node_id')
                log_events = log.get('events', [])
                
                for event in log_events:
                    if event.get('type') == 'message':
                        # 只发送尚未发送过的消息
                        if node_id not in sent_message_nodes:
                            events.append({
                                'type': 'message',
                                'content': event.get('content', ''),
                                'message_type': event.get('message_type', 'text'),
                                'from_subflow': True,
                                'subflow_name': subflow_name,
                            })
                            sent_message_nodes.append(node_id)
        
        # 在等待配置中添加子流程标识
        forwarded_config = {
            **waiting_config,
            'from_subflow': True,
            'subflow_name': subflow_name,
            # 保存子流程状态以便恢复
            '_subflow_state': {
                **subflow_state,
                'outputs': subflow_result.get('outputs', {}),
                'logs': subflow_result.get('logs', []),
                'total_tokens': subflow_result.get('total_tokens', 0),
                'sent_message_nodes': sent_message_nodes,  # 始终保存，即使为空列表
            },
        }
        
        return NodeResult(
            success=True,
            output=f"子流程等待用户输入",
            waiting_for_input=True,
            waiting_config=forwarded_config,
            elapsed_time=elapsed_time,
            events=events if events else None,
        )
    
    async def _resume_subflow(
        self,
        subflow_state: Dict[str, Any],
        inputs: Dict[str, Any],
        parent_context: NodeContext,
        depth: int,
        parent_workflows: List[str],
    ) -> Dict[str, Any]:
        """从等待状态恢复子流程执行"""
        # 恢复子流程状态
        current_node_id = subflow_state.get('current_node_id')
        node_map = subflow_state.get('node_map', {})
        edge_map = subflow_state.get('edge_map', {})
        parallel_edge_map = subflow_state.get('parallel_edge_map', {})
        saved_outputs = subflow_state.get('outputs', {})
        saved_logs = subflow_state.get('logs', [])
        saved_tokens = subflow_state.get('total_tokens', 0)
        loop_state = subflow_state.get('loop_state')  # 循环状态
        subflow_id = subflow_state.get('subflow_id', '')
        
        # 创建子流程上下文，恢复之前的变量
        subflow_context = NodeContext(
            workflow_run_id=f"{parent_context.workflow_run_id}_sub_resume",
            variables={**saved_outputs, **inputs},
            user_input=parent_context.user_input,
            user_id=parent_context.user_id,
            conversation_history=parent_context.conversation_history.copy(),
            db_session=parent_context.db_session,
            metadata={
                'subflow_depth': depth,
                'parent_workflows': parent_workflows,
                'parent_run_id': parent_context.workflow_run_id,
            },
        )
        
        # 设置用户输入（交互式节点会读取这个值）
        subflow_context.variables['__user_input__'] = parent_context.variables.get('__user_input__')
        
        logs = saved_logs.copy()
        total_tokens = saved_tokens
        
        # 检查是否从循环中恢复
        if loop_state:
            loop_node_id = loop_state.get('loop_node_id')
            loop_node_config = node_map.get(loop_node_id, {})
            loop_config = loop_node_config.get('data', {})
            
            # 继续执行循环，从暂停的节点恢复
            loop_result = await self._execute_loop_in_subflow(
                node_map, edge_map, parallel_edge_map, loop_node_id,
                loop_config, subflow_context, logs, subflow_id,
                resume_node_id=current_node_id  # 从暂停的节点继续执行
            )
            
            total_tokens += loop_result.get('total_tokens', 0)
            
            # 检查循环是否因等待用户输入而暂停
            if loop_result.get('waiting_for_input'):
                return loop_result
            
            # 检查循环是否失败
            if not loop_result.get('success', True):
                return loop_result
            
            # 获取循环结果
            loop_results = subflow_context.variables.get('_loop_results', [])
            output_var = loop_config.get('output_variable', 'loop_results')
            subflow_context.variables[output_var] = loop_results
            
            # 循环完成后从循环节点的输出边继续
            next_nodes = edge_map.get(loop_node_id, [])
            child_node_ids = self._get_child_nodes(node_map, loop_node_id)
            next_nodes = [n for n in next_nodes if n not in child_node_ids]
            current_node_id = next_nodes[0] if next_nodes else None
            
            # 清除 __user_input__
            if '__user_input__' in subflow_context.variables:
                del subflow_context.variables['__user_input__']
        
        # 从当前节点继续执行（先重新执行当前等待的节点）
        while current_node_id:
            node_config = node_map.get(current_node_id)
            if not node_config:
                break
            
            node_type = node_config.get('type', '')
            node_label = node_config.get('data', {}).get('label', current_node_id)
            
            # 结束节点
            if node_type == 'end':
                node_instance = NodeRegistry.create_instance(node_type, node_config.get('data', {}))
                if node_instance:
                    result = node_instance.execute(subflow_context)
                    logs.append({
                        'node_id': current_node_id,
                        'node_type': node_type,
                        'node_label': node_label,
                        'status': 'completed',
                        'output': result.output,
                    })
                break
            
            # 创建并执行节点
            node_instance = NodeRegistry.create_instance(node_type, node_config.get('data', {}))
            if not node_instance:
                logger.warning(f'[子流程恢复] 未知节点类型: {node_type}')
                next_nodes = edge_map.get(current_node_id, [])
                current_node_id = next_nodes[0] if next_nodes else None
                continue
            
            # 执行节点
            start_time = time.time()
            result = await node_instance.execute_async(subflow_context)
            elapsed = int((time.time() - start_time) * 1000)
            
            # 循环节点：执行循环体
            if node_type == 'loop':
                loop_node_id = current_node_id
                loop_config = node_config.get('data', {})
                
                # 记录循环节点初始化日志
                logs.append({
                    'node_id': current_node_id,
                    'node_type': node_type,
                    'node_label': node_label,
                    'status': 'completed' if result.success else 'failed',
                    'output': result.output,
                    'elapsed_time': elapsed,
                })
                
                if result.success:
                    # 更新上下文变量（循环节点会设置 _loop_items, _loop_index 等）
                    subflow_context.variables.update(result.output_variables)
                    
                    # 执行循环体
                    loop_result = await self._execute_loop_in_subflow(
                        node_map, edge_map, parallel_edge_map, loop_node_id,
                        loop_config, subflow_context, logs, subflow_id
                    )
                    
                    total_tokens += loop_result.get('total_tokens', 0)
                    
                    # 检查循环是否因等待用户输入而暂停
                    if loop_result.get('waiting_for_input'):
                        return loop_result
                    
                    # 检查循环是否失败
                    if not loop_result.get('success', True):
                        return loop_result
                    
                    # 获取循环结果
                    loop_results = subflow_context.variables.get('_loop_results', [])
                    output_var = loop_config.get('output_variable', 'loop_results')
                    subflow_context.variables[output_var] = loop_results
                
                # 循环完成后从循环节点的输出边继续
                next_nodes = edge_map.get(loop_node_id, [])
                child_node_ids = self._get_child_nodes(node_map, loop_node_id)
                next_nodes = [n for n in next_nodes if n not in child_node_ids]
                current_node_id = next_nodes[0] if next_nodes else None
                continue
            
            # 检查是否再次需要等待用户输入
            if result.waiting_for_input:
                log_entry = {
                    'node_id': current_node_id,
                    'node_type': node_type,
                    'node_label': node_label,
                    'status': 'waiting',
                    'output': result.output,
                    'elapsed_time': elapsed,
                }
                logs.append(log_entry)
                
                return {
                    'success': True,
                    'waiting_for_input': True,
                    'waiting_config': result.waiting_config,
                    'outputs': subflow_context.variables,
                    'logs': logs,
                    'total_tokens': total_tokens,
                    'subflow_state': {
                        'current_node_id': current_node_id,
                        'node_map': node_map,
                        'edge_map': edge_map,
                        'parallel_edge_map': parallel_edge_map,
                        'sent_message_nodes': subflow_state.get('sent_message_nodes', []),
                    },
                }
            
            # 更新最后一个等待状态的日志为完成
            if logs and logs[-1].get('status') == 'waiting' and logs[-1].get('node_id') == current_node_id:
                logs[-1]['status'] = 'completed' if result.success else 'failed'
                logs[-1]['output'] = result.output
                logs[-1]['elapsed_time'] = elapsed
            else:
                # 记录新日志
                log_entry = {
                    'node_id': current_node_id,
                    'node_type': node_type,
                    'node_label': node_label,
                    'status': 'completed' if result.success else 'failed',
                    'output': result.output,
                    'error': result.error,
                    'elapsed_time': elapsed,
                    'tokens_used': result.tokens_used,
                }
                if result.events:
                    log_entry['events'] = result.events
                logs.append(log_entry)
            
            total_tokens += result.tokens_used
            
            if not result.success:
                return {
                    'success': False,
                    'error': f'子流程节点 {node_label} 执行失败: {result.error}',
                    'outputs': subflow_context.variables,
                    'logs': logs,
                    'total_tokens': total_tokens,
                }
            
            # 更新上下文
            subflow_context.variables.update(result.output_variables)
            subflow_context.previous_output = result.output
            
            # 保存节点输出到命名空间
            subflow_context.variables[f'_node_{current_node_id}'] = {
                'output': result.output,
                **result.output_variables,
            }
            
            # 清除 __user_input__，避免下一个交互式节点读取到上一个节点的输入
            if '__user_input__' in subflow_context.variables:
                del subflow_context.variables['__user_input__']
            
            # 确定下一个节点
            if result.next_node_id:
                if result.next_node_id in parallel_edge_map.get(current_node_id, {}):
                    current_node_id = parallel_edge_map[current_node_id][result.next_node_id]
                elif result.next_node_id in node_map:
                    current_node_id = result.next_node_id
                else:
                    next_nodes = edge_map.get(current_node_id, [])
                    current_node_id = next_nodes[0] if next_nodes else None
            else:
                next_nodes = edge_map.get(current_node_id, [])
                current_node_id = next_nodes[0] if next_nodes else None
        
        return {
            'success': True,
            'outputs': subflow_context.variables,
            'logs': logs,
            'total_tokens': total_tokens,
            'subflow_state': {
                'sent_message_nodes': subflow_state.get('sent_message_nodes', []),
            },
        }
    
    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'subflow_id': {
                    'type': 'string',
                    'title': '子流程ID',
                    'description': '要调用的子流程工作流ID',
                },
                'subflow_name': {
                    'type': 'string',
                    'title': '子流程名称',
                    'description': '子流程显示名称',
                },
                'var_pass_mode': {
                    'type': 'string',
                    'title': '变量传递模式',
                    'enum': ['all', 'selected', 'none'],
                    'default': 'all',
                },
                'selected_vars': {
                    'type': 'array',
                    'title': '选择传递的变量',
                    'items': {'type': 'string'},
                },
                'var_mapping': {
                    'type': 'object',
                    'title': '变量映射',
                    'description': '子流程变量名 -> 主流程变量名',
                },
                'result_pass_mode': {
                    'type': 'string',
                    'title': '结果传递模式',
                    'enum': ['all', 'selected', 'none'],
                    'default': 'all',
                },
                'result_vars': {
                    'type': 'array',
                    'title': '选择传递的结果变量',
                    'items': {'type': 'string'},
                },
                'result_variable': {
                    'type': 'string',
                    'title': '结果变量名',
                    'default': 'subflow_result',
                },
                'max_depth': {
                    'type': 'integer',
                    'title': '最大嵌套深度',
                    'default': 5,
                    'minimum': 1,
                    'maximum': 10,
                },
                'show_subflow_messages': {
                    'type': 'boolean',
                    'title': '显示子流程消息',
                    'description': '开启后，子流程中的消息节点会在主流程对话中显示',
                    'default': False,
                },
                'forward_interactive': {
                    'type': 'boolean',
                    'title': '转发交互式节点',
                    'description': '开启后，子流程中的问答、选项、确认等节点会在主流程中显示',
                    'default': False,
                },
            },
            'required': ['subflow_id'],
        }
