import { Message } from '@arco-design/web-react';
import { Edge } from '@xyflow/react';

export interface ValidationResult {
  isValid: boolean;
  errors: string[];
}

/**
 * 校验节点数据是否完整
 * @param nodeData 节点数据
 * @param nodeType 节点类型
 * @returns 校验结果
 */
export const validateNodeData = (nodeData: any, nodeType: string): ValidationResult => {
  const errors: string[] = [];

  // 检查基本字段
  if (!nodeData.title) {
    errors.push('节点标题不能为空');
  }

  // 根据不同节点类型进行特定校验
  switch (nodeType) {
    case 'REST':
      errors.push(...validateRestNode(nodeData));
      break;
    case 'CODE':
      errors.push(...validateCodeNode(nodeData));
      break;
    case 'SWITCH':
      errors.push(...validateSwitchNode(nodeData));
      break;
    case 'LOOP_START':
    case 'LOOP_END':
      errors.push(...validateLoopNode(nodeData, nodeType));
      break;
    // case 'EVENTSEND':
    // case 'EVENTLISTENE':
    //   errors.push(...validateEventNode(nodeData));
    //   break;
    case 'WAIT':
      errors.push(...validateWaitNode(nodeData));
      break;
    case 'CYCLE':
      errors.push(...validateCycleNode(nodeData));
      break;
    default:
      // 对于其他节点类型，检查基本参数
      errors.push(...validateBasicParams(nodeData));
      break;
  }

  return {
    isValid: errors.length === 0,
    errors
  };
};

/**
 * 校验REST节点
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateRestNode = (nodeData: any): string[] => {
  const errors: string[] = [];

  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('REST节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('REST节点配置信息格式错误');
    return errors;
  }

  if (!customDef.method) {
    errors.push('请求方法不能为空');
  }

  if (!customDef.url) {
    errors.push('URL地址不能为空');
  }
  else {
    // 基本的 URL 格式校验
    const urlPattern = /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;
    if (!urlPattern.test(customDef.url)) {
      errors.push('URL地址格式不正确');
    }
  }

  return errors;
};

/**
 * 校验代码节点
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateCodeNode = (nodeData: any): string[] => {
  const errors: string[] = [];

  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('代码节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('代码节点配置信息格式错误');
    return errors;
  }

  if (!customDef.sourceCode) {
    errors.push('代码内容不能为空');
  }

  return errors;
};

/**
 * 校验条件节点
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateSwitchNode = (nodeData: any): string[] => {
  const errors: string[] = [];

  // 检查条件表达式
  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('条件节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('条件节点配置信息格式错误');
    return errors;
  }

  // 检查是否有条件表达式
  if (!customDef.conditions || customDef.conditions.length === 0) {
    errors.push('请至少添加一个条件表达式');
  }

  // 检查每个条件表达式的完整性
  if (customDef.conditions && customDef.conditions.length > 0) {
    customDef.conditions.forEach((condition: any, index: number) => {
      if (!condition.apiOutId) {
        errors.push(`第${index + 1}个条件表达式的逻辑出口不能为空`);
      }
      if (!condition.expression) {
        errors.push(`第${index + 1}个条件表达式的表达式不能为空`);
      }
    });
  }

  return errors;
};

/**
 * 校验循环节点
 * @param nodeData 节点数据
 * @param nodeType 节点类型
 * @returns 错误信息数组
 */
const validateLoopNode = (nodeData: any, nodeType: string): string[] => {
  // LOOP_START 类型节点不需要校验
  if (nodeType === 'LOOP_START') {
    return [];
  }

  const errors: string[] = [];

  // 检查循环条件（仅针对 LOOP_END 节点）
  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('循环节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('循环节点配置信息格式错误');
    return errors;
  }

  // // 检查循环条件
  // if (!customDef.conditions || customDef.conditions.length === 0) {
  //   errors.push('请至少添加一个循环条件');
  // }

  return errors;
};

/**
 * 校验事件节点
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateEventNode = (nodeData: any): string[] => {
  const errors: string[] = [];

  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('事件节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('事件节点配置信息格式错误');
    return errors;
  }

  if (!customDef.eventId) {
    errors.push('请选择事件');
  }

  return errors;
};

/**
 * 校验等待节点
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateWaitNode = (nodeData: any): string[] => {
  const errors: string[] = [];

  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('等待节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('等待节点配置信息格式错误');
    return errors;
  }

  // 检查等待时间是否设置
  if (customDef.duration === undefined || customDef.duration === null) {
    errors.push('请设置等待时间');
  }
  else if (typeof customDef.duration !== 'number' || customDef.duration < 0) {
    errors.push('等待时间必须是非负数');
  }

  return errors;
};

/**
 * 校验周期节点
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateCycleNode = (nodeData: any): string[] => {
  const errors: string[] = [];

  if (!nodeData.component || !nodeData.component.customDef) {
    errors.push('周期节点配置信息不完整');
    return errors;
  }

  let customDef;
  try {
    customDef = typeof nodeData.component.customDef === 'string'
      ? JSON.parse(nodeData.component.customDef)
      : nodeData.component.customDef;
  } catch (e) {
    errors.push('周期节点配置信息格式错误');
    return errors;
  }

  // 检查 Cron 表达式是否设置
  if (!customDef.intervalSeconds) {
    errors.push('请设置 Cron 表达式');
  }

  return errors;
};

/**
 * 校验基本参数
 * @param nodeData 节点数据
 * @returns 错误信息数组
 */
const validateBasicParams = (nodeData: any): string[] => {
  const errors: string[] = [];

  // 检查BASIC节点是否有关联的组件实例
  if (nodeData.type === 'BASIC') {
    // 检查节点是否具有component属性和customDef属性
    console.log('nodeData:', nodeData);
    if (!nodeData.component || !nodeData.component.compIdentifier) {
      errors.push('基础节点缺少组件实例配置');
    }
  }

  // 检查输入参数的完整性
  if (nodeData.parameters?.dataIns) {
    nodeData.parameters.dataIns.forEach((param: any, index: number) => {
      if (!param.id) {
        errors.push(`第${index + 1}个输入参数的标识不能为空`);
      }
      if (!param.dataType) {
        errors.push(`第${index + 1}个输入参数的数据类型不能为空`);
      }
    });
  }

  // 检查输出参数的完整性
  if (nodeData.parameters?.dataOuts) {
    nodeData.parameters.dataOuts.forEach((param: any, index: number) => {
      if (!param.id) {
        errors.push(`第${index + 1}个输出参数的标识不能为空`);
      }
      if (!param.dataType) {
        errors.push(`第${index + 1}个输出参数的数据类型不能为空`);
      }
    });
  }

  return errors;
};

/**
 * 校验整个流程的所有节点
 * @param nodes 流程中的所有节点
 * @returns 校验结果
 */
export const validateAllNodes = (nodes: any[]): ValidationResult => {
  const allErrors: string[] = [];

  nodes.forEach((node, index) => {
    const nodeType = node.data?.type || node.type;
    const nodeName = node.data?.title || `节点${index + 1}`;

    const result = validateNodeData(node.data, nodeType);
    if (!result.isValid) {
      result.errors.forEach(error => {
        allErrors.push(`[${nodeName}] ${error}`);
      });
    }
  });

  return {
    isValid: allErrors.length === 0,
    errors: allErrors
  };
};

/**
 * 校验流程中的所有连接线
 * @param edges 流程中的所有连接线
 * @param nodes 流程中的所有节点（用于验证节点存在性）
 * @returns 校验结果
 */
export const validateAllEdges = (edges: Edge[], nodes: any[]): ValidationResult => {
  const allErrors: string[] = [];

  // 创建节点ID到节点标题的映射，方便错误信息展示
  const nodeTitleMap = new Map<string, string>();
  const nodeMap = new Map<string, any>();

  nodes.forEach(node => {
    const nodeTitle = node.data?.title || node.id;
    nodeTitleMap.set(node.id, nodeTitle);
    nodeMap.set(node.id, node);
  });

  // 检查连接线的基本信息
  edges.forEach((edge, index) => {
    // 检查连接线是否有源节点和目标节点
    if (!edge.source) {
      allErrors.push(`第${index + 1}条连接线缺少源节点`);
      return;
    }

    if (!edge.target) {
      allErrors.push(`第${index + 1}条连接线缺少目标节点`);
      return;
    }

    // 检查源节点和目标节点是否存在
    if (edge.source && !nodeTitleMap.has(edge.source)) {
      allErrors.push(`第${index + 1}条连接线的源节点"${edge.source}"不存在`);
    }

    if (edge.target && !nodeTitleMap.has(edge.target)) {
      allErrors.push(`第${index + 1}条连接线的目标节点"${edge.target}"不存在`);
    }
  });

  // 检查是否有未连接的节点（开始节点和结束节点除外）
  const connectedNodeIds = new Set<string>();
  edges.forEach(edge => {
    if (edge.source) connectedNodeIds.add(edge.source);
    if (edge.target) connectedNodeIds.add(edge.target);
  });

  nodes.forEach(node => {
    // 如果节点没有被任何连接线连接
    if (!connectedNodeIds.has(node.id)) {
      const nodeType = node.data?.type || node.type;
      // 开始节点和结束节点可以不连接
      if (nodeType !== 'start' && nodeType !== 'end') {
        const nodeName = node.data?.title || node.id;
        allErrors.push(`节点"${nodeName}"未连接任何连线`);
      }
    }
  });

  // 检查节点的连接是否符合规则
  const sourceCount = new Map<string, number>(); // 每个节点作为源节点的次数
  const targetCount = new Map<string, number>(); // 每个节点作为目标节点的次数

  edges.forEach(edge => {
    if (edge.source) {
      sourceCount.set(edge.source, (sourceCount.get(edge.source) || 0) + 1);
    }
    if (edge.target) {
      targetCount.set(edge.target, (targetCount.get(edge.target) || 0) + 1);
    }
  });

  // 检查每个节点的连接情况
  nodes.forEach(node => {
    const nodeId = node.id;
    const nodeType = node.data?.type || node.type;
    const nodeName = node.data?.title || node.id;
    const sourceEdges = sourceCount.get(nodeId) || 0;
    const targetEdges = targetCount.get(nodeId) || 0;


    // 特定节点类型可能有特殊的连接规则
    switch (nodeType) {
      case 'SWITCH':
        // 条件节点应该有至少一个输出连接
        if (sourceEdges === 0) {
          allErrors.push(`条件节点"${nodeName}"缺少输出连接`);
        }
        break;

      case 'start':
      case 'START':
        // 开始节点应该有输出连接，但不需要输入连接
        if (sourceEdges === 0) {
          allErrors.push(`开始节点"${nodeName}"缺少输出连接`);
        }
        break;

      case 'end':
      case 'END':
        // 结束节点应该有输入连接，但不需要输出连接
        if (targetEdges === 0) {
          allErrors.push(`结束节点"${nodeName}"缺少输入连接`);
        }
        break;

      default:
        // 其他节点应该至少有一个输入和一个输出连接
        if (targetEdges === 0) {
          allErrors.push(`节点"${nodeName}"缺少输入连接`);
        }
        if (sourceEdges === 0) {
          allErrors.push(`节点"${nodeName}"缺少输出连接`);
        }
        break;
    }
  });

  return {
    isValid: allErrors.length === 0,
    errors: allErrors
  };
};

/**
 * 显示校验错误信息
 * @param errors 错误信息数组
 */
export const showValidationErrors = (errors: string[]) => {
  if (errors.length > 0) {
    // 创建错误信息内容
    let content = '存在以下问题需要修正：\n';
    content += errors.map((error, index) => `${index + 1}. ${error}`).join('\n');

    // 发送错误信息到 logBar
    const logEvent = new CustomEvent('logMessage', {
      detail: {
        type: 'validation',
        message: content,
        timestamp: new Date().toISOString()
      }
    });
    document.dispatchEvent(logEvent);

    Message.error({
      content: content,
      duration: 5000
    });
  }
};
