"""
循环节点

支持两种循环模式：
1. for_each - 遍历数组，对每个元素执行循环体
2. while - 条件循环，满足条件时持续执行
"""
import ast
import json
import logging
import operator
from typing import Any, Dict, List

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

logger = logging.getLogger(__name__)


@NodeRegistry.register
class LoopNode(BaseNode):
    """
    循环节点
    
    支持 for_each 和 while 两种循环模式
    """
    
    node_type = 'loop'
    node_name = '循环'
    node_category = 'logic'
    node_icon = 'repeat'
    node_description = '循环执行一组节点，支持遍历数组或条件循环'
    
    supports_branches = True
    
    inputs = [
        {
            'name': 'items',
            'type': 'array',
            'description': '要遍历的数组（for_each 模式）',
        },
    ]
    
    outputs = [
        {
            'name': 'results',
            'type': 'array',
            'description': '每次循环的结果数组',
        },
        {
            'name': 'current_item',
            'type': 'any',
            'description': '当前循环项（循环体内可用）',
        },
        {
            'name': 'current_index',
            'type': 'number',
            'description': '当前循环索引（从 0 开始）',
        },
    ]
    
    # 支持的操作符（用于 while 条件判断）
    OPERATORS = {
        'eq': operator.eq,          # 等于
        'ne': operator.ne,          # 不等于
        'gt': operator.gt,          # 大于
        'gte': operator.ge,         # 大于等于
        'lt': operator.lt,          # 小于
        'lte': operator.le,         # 小于等于
        'is_empty': lambda a, _: not a,  # 为空
        'is_not_empty': lambda a, _: bool(a),  # 不为空
        'is_true': lambda a, _: bool(a),  # 为真
        'is_false': lambda a, _: not bool(a),  # 为假
    }
    
    def execute(self, context: NodeContext) -> NodeResult:
        """
        执行循环节点
        
        循环节点本身只负责初始化循环状态，实际的循环执行由 WorkflowService 处理
        """
        try:
            loop_mode = self.config.get('loop_mode', 'for_each')
            max_iterations = self.config.get('max_iterations', 100)
            
            if loop_mode == 'for_each':
                return self._init_for_each(context, max_iterations)
            elif loop_mode == 'while':
                return self._init_while(context, max_iterations)
            else:
                return NodeResult(
                    success=False,
                    error=f'不支持的循环模式: {loop_mode}',
                )
                
        except Exception as e:
            logger.exception(f'循环节点执行失败: {e}')
            return NodeResult(
                success=False,
                error=str(e),
            )
    
    def _init_for_each(self, context: NodeContext, max_iterations: int) -> NodeResult:
        """初始化 for_each 循环"""
        items_var = self.config.get('items_variable', '')
        
        logger.info(f'[LoopNode] 初始化 for_each 循环，items_variable={items_var}')
        
        # 解析数组变量
        items = self._resolve_variable(items_var, context)
        
        logger.info(f'[LoopNode] 解析后的 items 类型: {type(items).__name__}, 值: {items}')
        
        # 如果是字符串，尝试解析为 JSON 或 Python 字面量
        if isinstance(items, str):
            try:
                items = json.loads(items)
                logger.info(f'[LoopNode] JSON 解析成功，items={items}')
            except json.JSONDecodeError:
                # 尝试使用 ast.literal_eval 解析 Python 字面量（如 str() 输出的列表）
                try:
                    items = ast.literal_eval(items)
                    logger.info(f'[LoopNode] Python 字面量解析成功，items={items}')
                except (ValueError, SyntaxError):
                    # 尝试按逗号分割（仅当不是列表/字典格式时）
                    if not (items.strip().startswith('[') or items.strip().startswith('{')):
                        items = [item.strip() for item in items.split(',') if item.strip()]
                        logger.info(f'[LoopNode] 按逗号分割，items={items}')
                    else:
                        logger.error(f'[LoopNode] 无法解析 items 字符串: {items[:200]}...')
                        return NodeResult(
                            success=False,
                            error=f'无法解析 items 变量，格式不正确',
                        )
        
        if not isinstance(items, (list, tuple)):
            error_msg = f'items 必须是数组，当前类型: {type(items).__name__}, 值: {items}, items_variable={items_var}'
            logger.error(f'[LoopNode] {error_msg}')
            return NodeResult(
                success=False,
                error=error_msg,
            )
        
        # 检查数组是否为空
        if len(items) == 0:
            logger.warning(f'[LoopNode] items 数组为空，items_variable={items_var}')
            # 返回成功但不执行循环体
        
        # 限制最大迭代次数
        if len(items) > max_iterations:
            logger.warning(f'数组长度 {len(items)} 超过最大迭代次数 {max_iterations}，将被截断')
            items = list(items)[:max_iterations]
        
        return NodeResult(
            success=True,
            output={
                'items': list(items),
                'total_count': len(items),
            },
            output_variables={
                '_loop_items': list(items),
                '_loop_index': 0,
                '_loop_total': len(items),
                '_loop_mode': 'for_each',
                '_loop_results': [],
            },
            metadata={
                'is_loop': True,
                'loop_mode': 'for_each',
                'total_iterations': len(items),
                'max_iterations': max_iterations,
            },
        )
    
    def _init_while(self, context: NodeContext, max_iterations: int) -> NodeResult:
        """初始化 while 循环"""
        # 检查初始条件
        condition_met = self._evaluate_condition(context)
        
        return NodeResult(
            success=True,
            output={
                'condition_met': condition_met,
            },
            output_variables={
                '_loop_index': 0,
                '_loop_mode': 'while',
                '_loop_condition_met': condition_met,
                '_loop_results': [],
                '_loop_max_iterations': max_iterations,
            },
            metadata={
                'is_loop': True,
                'loop_mode': 'while',
                'condition_met': condition_met,
                'max_iterations': max_iterations,
            },
        )
    
    def check_continue(self, context: NodeContext) -> bool:
        """
        检查是否继续循环
        
        由 WorkflowService 在每次循环迭代后调用
        """
        loop_mode = context.get_variable('_loop_mode')
        current_index = context.get_variable('_loop_index', 0)
        max_iterations = self.config.get('max_iterations', 100)
        
        # 检查最大迭代次数
        if current_index >= max_iterations:
            logger.warning(f'达到最大迭代次数 {max_iterations}，停止循环')
            return False
        
        if loop_mode == 'for_each':
            total = context.get_variable('_loop_total', 0)
            return current_index < total
        elif loop_mode == 'while':
            return self._evaluate_condition(context)
        
        return False
    
    def get_current_item(self, context: NodeContext) -> Any:
        """获取当前循环项（for_each 模式）"""
        items = context.get_variable('_loop_items', [])
        index = context.get_variable('_loop_index', 0)
        
        if 0 <= index < len(items):
            return items[index]
        return None
    
    def increment_index(self, context: NodeContext) -> int:
        """增加循环索引"""
        current_index = context.get_variable('_loop_index', 0)
        new_index = current_index + 1
        context.set_variable('_loop_index', new_index)
        return new_index
    
    def add_result(self, context: NodeContext, result: Any) -> None:
        """添加循环结果"""
        results = context.get_variable('_loop_results', [])
        results.append(result)
        context.set_variable('_loop_results', results)
    
    def _resolve_variable(self, variable: str, context: NodeContext) -> Any:
        """解析变量引用，支持多层路径访问"""
        if not isinstance(variable, str):
            return variable
        
        # 如果是空字符串，返回 None
        if not variable.strip():
            return None
            
        # 检查是否是 {{...}} 格式的变量引用
        if not (variable.startswith('{{') and variable.endswith('}}')):
            # 不是变量引用，直接返回原始字符串值（可能是硬编码的 JSON 数组或逗号分隔的值）
            return variable
        
        # 使用 resolve_template 解析变量，它支持多层路径访问（如 node.key.subkey）
        resolved = context.resolve_template(variable)
        
        # 如果解析结果与原始变量相同，说明变量不存在或解析失败
        if resolved == variable:
            return None
        
        # 如果解析结果是字符串，尝试解析为 JSON
        if isinstance(resolved, str):
            try:
                import json
                return json.loads(resolved)
            except (json.JSONDecodeError, TypeError):
                return resolved
        
        return resolved
    
    def _evaluate_condition(self, context: NodeContext) -> bool:
        """评估 while 条件"""
        conditions = self.config.get('conditions', [])
        logic = self.config.get('condition_logic', 'and')  # and 或 or
        
        if not conditions:
            return False  # 无条件默认不继续
        
        results = []
        for condition in conditions:
            result = self._evaluate_single_condition(condition, context)
            results.append(result)
        
        if logic == 'or':
            return any(results)
        else:  # and
            return all(results)
    
    def _evaluate_single_condition(self, condition: Dict, context: NodeContext) -> bool:
        """评估单个条件"""
        variable = condition.get('variable', '')
        op_name = condition.get('operator', 'eq')
        value = condition.get('value', '')
        
        # 解析变量和值
        left_val = self._resolve_variable(variable, context)
        right_val = self._resolve_variable(value, context) if value else None
        
        # 获取操作符函数
        op_func = self.OPERATORS.get(op_name, operator.eq)
        
        try:
            # 特殊处理不需要右值的操作符
            if op_name in ['is_empty', 'is_not_empty', 'is_true', 'is_false']:
                return op_func(left_val, None)
            
            # 尝试类型转换
            if isinstance(left_val, (int, float)) and isinstance(right_val, str):
                try:
                    if '.' in right_val:
                        right_val = float(right_val)
                    else:
                        right_val = int(right_val)
                except ValueError:
                    pass
            
            return op_func(left_val, right_val)
        except Exception as e:
            logger.warning(f'条件评估失败: {e}')
            return False
    
    @classmethod
    def get_config_schema(cls) -> Dict[str, Any]:
        """获取配置 Schema"""
        return {
            'type': 'object',
            'properties': {
                'loop_mode': {
                    'type': 'string',
                    'title': '循环模式',
                    'enum': ['for_each', 'while'],
                    'enumNames': ['遍历数组 (For Each)', '条件循环 (While)'],
                    'default': 'for_each',
                },
                'items_variable': {
                    'type': 'string',
                    'title': '数组变量',
                    'description': '要遍历的数组变量名（for_each 模式）',
                },
                'item_variable_name': {
                    'type': 'string',
                    'title': '循环项变量名',
                    'description': '当前循环项的变量名，默认为 item',
                    'default': 'item',
                },
                'index_variable_name': {
                    'type': 'string',
                    'title': '索引变量名',
                    'description': '当前索引的变量名，默认为 index',
                    'default': 'index',
                },
                'conditions': {
                    'type': 'array',
                    'title': '循环条件',
                    'description': 'while 模式的循环条件',
                    'items': {
                        'type': 'object',
                        'properties': {
                            'variable': {
                                'type': 'string',
                                'title': '变量',
                            },
                            'operator': {
                                'type': 'string',
                                'title': '操作符',
                                'enum': list(cls.OPERATORS.keys()),
                                'default': 'eq',
                            },
                            'value': {
                                'type': 'string',
                                'title': '比较值',
                            },
                        },
                    },
                },
                'condition_logic': {
                    'type': 'string',
                    'title': '条件逻辑',
                    'enum': ['and', 'or'],
                    'enumNames': ['全部满足 (AND)', '任一满足 (OR)'],
                    'default': 'and',
                },
                'max_iterations': {
                    'type': 'integer',
                    'title': '最大迭代次数',
                    'description': '防止无限循环，默认 100 次',
                    'default': 100,
                    'minimum': 1,
                    'maximum': 10000,
                },
                'output_variable': {
                    'type': 'string',
                    'title': '输出变量名',
                    'description': '存储所有循环结果的变量名',
                    'default': 'loop_results',
                },
            },
        }


