import { Node, Connection } from 'reactflow';
import { NodeType, DataType, DataFlow } from '../types/canvas';

/**
 * 连接验证器 - 验证节点间的连接是否有效
 */
export class ConnectionValidator {
  /**
   * 验证连接是否有效
   */
  static validateConnection(
    connection: Connection,
    nodes: Node[]
  ): { valid: boolean; reason?: string } {
    const sourceNode = nodes.find(n => n.id === connection.source);
    const targetNode = nodes.find(n => n.id === connection.target);

    if (!sourceNode || !targetNode) {
      return { valid: false, reason: '找不到源节点或目标节点' };
    }

    // 防止自连接
    if (connection.source === connection.target) {
      return { valid: false, reason: '不能连接到自身' };
    }

    // 防止循环连接
    if (this.wouldCreateCycle(connection, nodes)) {
      return { valid: false, reason: '连接会创建循环依赖' };
    }

    // 检查数据类型兼容性
    const sourceOutputType = this.getNodeOutputType(sourceNode.type as NodeType);
    const targetInputType = this.getNodeInputType(targetNode.type as NodeType);

    if (!this.areTypesCompatible(sourceOutputType, targetInputType)) {
      return { 
        valid: false, 
        reason: `数据类型不兼容: ${sourceOutputType} → ${targetInputType}` 
      };
    }

    // 检查是否已存在连接
    const existingConnections = this.getExistingConnections(nodes);
    const isDuplicate = existingConnections.some(edge => 
      edge.source === connection.source && 
      edge.target === connection.target
    );

    if (isDuplicate) {
      return { valid: false, reason: '连接已存在' };
    }

    return { valid: true };
  }

  /**
   * 检查是否会创建循环
   */
  private static wouldCreateCycle(connection: Connection, nodes: Node[]): boolean {
    // 简化的循环检测 - 检查目标节点是否能到达源节点
    const visited = new Set<string>();
    const stack = [connection.target];

    while (stack.length > 0) {
      const currentId = stack.pop()!;
      if (currentId === connection.source) {
        return true; // 发现循环
      }

      if (visited.has(currentId)) {
        continue;
      }
      visited.add(currentId);

      // 找到当前节点的所有输出连接
      const outgoingConnections = this.getExistingConnections(nodes)
        .filter(edge => edge.source === currentId);
      
      for (const edge of outgoingConnections) {
        stack.push(edge.target);
      }
    }

    return false;
  }

  /**
   * 获取现有连接
   */
  private static getExistingConnections(nodes: Node[]): Array<{source: string, target: string}> {
    // 这里应该从实际的边数据中获取，暂时返回空数组
    return [];
  }

  /**
   * 检查数据类型是否兼容
   */
  private static areTypesCompatible(sourceType: DataType, targetType: DataType): boolean {
    // 完全匹配
    if (sourceType === targetType) return true;

    // 批量数据兼容性
    if (sourceType === 'batch') {
      // 批量数据可以连接到任何类型（取第一个元素）
      return true;
    }

    if (targetType === 'batch') {
      // 任何类型都可以转换为批量数据
      return true;
    }

    // 特殊兼容性规则
    const compatibilityRules: Record<DataType, DataType[]> = {
      'text': ['text'],
      'image': ['image', 'video'], // 图片可以用于视频生成
      'video': ['video'],
      'batch': ['text', 'image', 'video', 'batch']
    };

    return compatibilityRules[sourceType]?.includes(targetType) || false;
  }

  /**
   * 获取节点输出类型
   */
  private static getNodeOutputType(nodeType: NodeType): DataType {
    const outputTypes: Record<NodeType, DataType> = {
      'textInput': 'text',
      'promptOptimize': 'text',
      'textDisplay': 'text',
      'imageUpload': 'image',
      'imageGenerate': 'image',
      'imageEdit': 'image',
      'imageDisplay': 'image',
      'videoGenerate': 'video',
      'videoPlayer': 'video',
      'folderUpload': 'batch',
      'batchGrid': 'batch'
    };

    return outputTypes[nodeType] || 'text';
  }

  /**
   * 获取节点输入类型
   */
  private static getNodeInputType(nodeType: NodeType): DataType {
    const inputTypes: Record<NodeType, DataType> = {
      'textInput': 'text',
      'promptOptimize': 'text',
      'textDisplay': 'text',
      'imageUpload': 'image',
      'imageGenerate': 'text', // 接受提示词
      'imageEdit': 'image',
      'imageDisplay': 'image',
      'videoGenerate': 'image', // 接受源图片
      'videoPlayer': 'video',
      'folderUpload': 'batch',
      'batchGrid': 'batch'
    };

    return inputTypes[nodeType] || 'text';
  }
}

/**
 * 数据流转换器 - 处理不同数据类型之间的转换
 */
export class DataFlowConverter {
  /**
   * 转换数据流以匹配目标节点类型
   */
  static convertDataFlow(
    sourceData: DataFlow,
    sourceNodeType: NodeType,
    targetNodeType: NodeType
  ): DataFlow {
    const targetInputType = ConnectionValidator['getNodeInputType'](targetNodeType);

    // 如果类型完全匹配，直接返回
    if (sourceData.dataType === targetInputType) {
      return sourceData;
    }

    // 批量到单个的转换
    if (sourceData.type === 'batch' && targetInputType !== 'batch') {
      return {
        type: 'single',
        dataType: targetInputType,
        content: this.extractFirstFromBatch(sourceData.content),
        metadata: {
          ...sourceData.metadata,
          convertedFrom: 'batch',
          originalCount: sourceData.content?.length || 0
        }
      };
    }

    // 单个到批量的转换
    if (sourceData.type === 'single' && targetInputType === 'batch') {
      return {
        type: 'batch',
        dataType: sourceData.dataType,
        content: [sourceData.content],
        metadata: {
          ...sourceData.metadata,
          convertedFrom: 'single',
          totalItems: 1,
          completedItems: 1
        }
      };
    }

    // 特殊转换规则
    return this.applySpecialConversions(sourceData, sourceNodeType, targetNodeType);
  }

  /**
   * 从批量数据中提取第一个元素
   */
  private static extractFirstFromBatch(batchContent: any[]): any {
    if (!Array.isArray(batchContent) || batchContent.length === 0) {
      return null;
    }

    const firstItem = batchContent[0];
    
    // 如果是批量结果对象，提取实际结果
    if (firstItem && typeof firstItem === 'object' && 'result' in firstItem) {
      return firstItem.result;
    }

    return firstItem;
  }

  /**
   * 应用特殊转换规则
   */
  private static applySpecialConversions(
    sourceData: DataFlow,
    sourceNodeType: NodeType,
    targetNodeType: NodeType
  ): DataFlow {
    // 图片到视频的转换
    if (sourceData.dataType === 'image' && targetNodeType === 'videoGenerate') {
      return {
        ...sourceData,
        metadata: {
          ...sourceData.metadata,
          convertedFor: 'videoGeneration'
        }
      };
    }

    // 文本到图片生成的转换
    if (sourceData.dataType === 'text' && targetNodeType === 'imageGenerate') {
      return {
        ...sourceData,
        metadata: {
          ...sourceData.metadata,
          convertedFor: 'imageGeneration'
        }
      };
    }

    // 默认返回原数据
    return sourceData;
  }

  /**
   * 根据目标节点类型准备数据
   */
  static prepareDataForNode(
    data: any,
    sourceNodeType: NodeType,
    targetNodeType: NodeType
  ): Record<string, any> {
    const updates: Record<string, any> = {};

    switch (targetNodeType) {
      case 'promptOptimize':
        updates.inputPrompt = data;
        break;
      case 'imageGenerate':
        updates.prompt = data;
        break;
      case 'imageEdit':
        if (sourceNodeType.includes('image')) {
          updates.originalImage = data;
        } else {
          updates.editInstruction = data;
        }
        break;
      case 'videoGenerate':
        if (sourceNodeType.includes('image')) {
          updates.sourceImage = data;
        } else {
          updates.motionPrompt = data;
        }
        break;
      case 'textDisplay':
        updates.inputText = data;
        updates.result = data;
        break;
      case 'imageDisplay':
        updates.inputImage = data;
        updates.result = data;
        break;
      case 'videoPlayer':
        updates.inputVideo = data;
        updates.result = data;
        break;
      case 'batchGrid':
        if (Array.isArray(data)) {
          updates.results = data.map((item: any, index: number) => ({
            id: `item-${index}`,
            filename: item.filename || `Item ${index + 1}`,
            status: 'success',
            result: item.result || item,
            thumbnail: item.thumbnail || (typeof item.result === 'string' ? item.result : undefined)
          }));
          updates.totalCount = data.length;
          updates.completedCount = data.length;
        } else {
          updates.results = [{
            id: 'item-0',
            filename: 'Single Item',
            status: 'success',
            result: data,
            thumbnail: typeof data === 'string' ? data : undefined
          }];
          updates.totalCount = 1;
          updates.completedCount = 1;
        }
        break;
      default:
        updates.result = data;
    }

    return updates;
  }
}
