/**
 * Copyright (c) 2025 TWork Team. All rights reserved.
 * This source code is licensed under the TWork License.
 */

/**
 * Bug 诊断引擎 (性能优化版 v2.0)
 * 
 * 提供错误模式匹配、堆栈分析、修复建议生成等能力
 * 
 * 优化策略:
 * 1. 错误模式库扩展: 从9种扩展到50+种
 * 2. 堆栈解析优化: 支持更多语言格式(Go/Rust/PHP等)
 * 3. 诊断缓存优化: 基于错误指纹的智能缓存
 * 4. LLM驱动诊断: 引入轻量级LLM辅助生成修复建议
 * 
 * v2.0 新增:
 * - 50+种错误模式
 * - 多语言堆栈解析(TS/Python/Java/Go/Rust/PHP)
 * - 测试用例生成器
 * - 错误指纹缓存
 */

// 简单的诊断结果缓存
const diagnosisCache = new Map<string, { result: BugDiagnosisResult; timestamp: number }>();
const CACHE_TTL = 5 * 60 * 1000; // 5分钟

export interface BugLocation {
  file: string;
  line: number;
  column?: number;
  function?: string;
}

export interface ErrorPattern {
  type: string;
  severity: 'critical' | 'high' | 'medium' | 'low';
  description: string;
  commonCauses: string[];
  suggestedFixes: string[];
}

export interface BugDiagnosisResult {
  errorType: string;
  rootCause: string;
  severity: 'critical' | 'high' | 'medium' | 'low';
  location?: BugLocation;
  suggestedFix: string;
  relatedFiles: string[];
  testCases: string[];
  confidence: number; // 0-1
  errorPattern?: ErrorPattern;
}

export interface BugDiagnosisOptions {
  sourceCode?: string;
  recentChanges?: string[];
  language?: string;
}

export interface BugLocationInternal {
  file: string;
  line: number;
  column?: number;
  function?: string;
}

/**
 * 常见错误模式库 (v2.0 - 50+种错误模式)
 */
const ERROR_PATTERNS: ErrorPattern[] = [
  // ========== TypeScript/JavaScript 错误 ==========
  {
    type: 'TypeError',
    severity: 'high',
    description: '类型错误,通常是访问了 undefined 或 null 的属性',
    commonCauses: [
      '未检查对象是否存在就访问属性',
      '函数返回值可能为 undefined',
      '异步数据未正确处理'
    ],
    suggestedFixes: [
      '使用可选链操作符 (?.)',
      '添加空值检查 (if (obj && obj.prop))',
      '使用 TypeScript 严格模式'
    ]
  },
  {
    type: 'ReferenceError',
    severity: 'high',
    description: '引用错误,使用了未声明的变量',
    commonCauses: [
      '变量拼写错误',
      '变量作用域问题',
      '未导入依赖'
    ],
    suggestedFixes: [
      '检查变量拼写',
      '确认变量在作用域内',
      '添加必要的 import 语句'
    ]
  },
  {
    type: 'SyntaxError',
    severity: 'critical',
    description: '语法错误,代码不符合语言规范',
    commonCauses: [
      '缺少括号或分号',
      '字符串未正确闭合',
      '使用了保留字'
    ],
    suggestedFixes: [
      '检查括号匹配',
      '使用 ESLint 自动修复',
      '检查字符串引号'
    ]
  },
  {
    type: 'RangeError',
    severity: 'medium',
    description: '范围错误,值超出有效范围',
    commonCauses: [
      '数组索引越界',
      '递归深度过大',
      '数字超出安全整数范围'
    ],
    suggestedFixes: [
      '添加边界检查',
      '使用迭代替代递归',
      '使用 BigInt 处理大数'
    ]
  },
  {
    type: 'URIError',
    severity: 'low',
    description: 'URI 处理错误,URL 编码/解码失败',
    commonCauses: [
      'URL 格式不正确',
      '编码字符无效',
      'URI 组件不完整'
    ],
    suggestedFixes: [
      '使用 encodeURIComponent()',
      '验证 URL 格式',
      '捕获 decodeURIComponent 异常'
    ]
  },
  {
    type: 'EvalError',
    severity: 'medium',
    description: 'eval() 函数执行错误',
    commonCauses: [
      '执行了无效的代码',
      '代码字符串格式错误',
      '作用域问题'
    ],
    suggestedFixes: [
      '避免使用 eval()',
      '使用 JSON.parse() 替代',
      '检查代码字符串格式'
    ]
  },
  {
    type: 'AggregateError',
    severity: 'high',
    description: '多个错误被包装为一个错误',
    commonCauses: [
      'Promise.allSettled 中多个失败',
      '批量操作部分失败',
      '并发请求错误'
    ],
    suggestedFixes: [
      '检查 errors 数组获取详细错误',
      '使用 Promise.allSettled 处理部分失败',
      '添加错误重试机制'
    ]
  },
  // Python 错误
  {
    type: 'TypeError',
    severity: 'high',
    description: '类型错误,操作应用于不适当类型',
    commonCauses: [
      '字符串和数字拼接',
      '函数参数类型不匹配',
      'NoneType 对象调用方法'
    ],
    suggestedFixes: [
      '使用类型转换 (str(), int())',
      '添加类型检查',
      '使用类型提示 (type hints)'
    ]
  },
  {
    type: 'IndexError',
    severity: 'medium',
    description: '索引错误,序列索引超出范围',
    commonCauses: [
      '列表/数组索引越界',
      '空列表访问',
      '负数索引使用不当'
    ],
    suggestedFixes: [
      '检查列表长度再访问',
      '使用 try-except 捕获',
      '使用安全的索引访问方法'
    ]
  },
  {
    type: 'KeyError',
    severity: 'medium',
    description: '键错误,字典中不存在该键',
    commonCauses: [
      '字典键拼写错误',
      '键未初始化',
      '使用了错误的键类型'
    ],
    suggestedFixes: [
      '使用 dict.get(key, default)',
      '检查键是否存在 (key in dict)',
      '使用 defaultdict'
    ]
  },
  {
    type: 'ValueError',
    severity: 'medium',
    description: '值错误,参数值不合法',
    commonCauses: [
      '类型转换失败',
      '参数超出有效范围',
      '格式字符串错误'
    ],
    suggestedFixes: [
      '添加参数验证',
      '使用 try-except 捕获',
      '检查输入值范围'
    ]
  },
  {
    type: 'AttributeError',
    severity: 'high',
    description: '属性错误,对象没有该属性',
    commonCauses: [
      '属性拼写错误',
      '对象类型不正确',
      '模块未正确导入'
    ],
    suggestedFixes: [
      '检查属性拼写',
      '使用 hasattr() 检查',
      '确认对象类型'
    ]
  },
  {
    type: 'NameError',
    severity: 'high',
    description: '名称错误,变量或函数未定义',
    commonCauses: [
      '变量未声明',
      '拼写错误',
      '作用域问题'
    ],
    suggestedFixes: [
      '检查变量拼写',
      '确认变量已声明',
      '检查作用域'
    ]
  },
  {
    type: 'FileNotFoundError',
    severity: 'high',
    description: '文件未找到错误',
    commonCauses: [
      '文件路径错误',
      '文件不存在',
      '权限不足'
    ],
    suggestedFixes: [
      '验证文件路径',
      '使用 os.path.exists() 检查',
      '检查文件权限'
    ]
  },
  {
    type: 'ImportError',
    severity: 'high',
    description: '导入错误,模块无法导入',
    commonCauses: [
      '模块未安装',
      '模块名错误',
      '循环导入'
    ],
    suggestedFixes: [
      'pip install 安装模块',
      '检查模块名拼写',
      '重构避免循环导入'
    ]
  },
  // Java 错误
  {
    type: 'NullPointerException',
    severity: 'critical',
    description: '空指针异常,访问 null 对象',
    commonCauses: [
      '未初始化对象',
      '方法返回 null',
      '数组元素为 null'
    ],
    suggestedFixes: [
      '添加 null 检查',
      '使用 Optional 类',
      '初始化对象'
    ]
  },
  {
    type: 'ArrayIndexOutOfBoundsException',
    severity: 'high',
    description: '数组索引越界',
    commonCauses: [
      '索引超出数组长度',
      '负数索引',
      '循环条件错误'
    ],
    suggestedFixes: [
      '检查数组长度',
      '使用边界检查',
      '修正循环条件'
    ]
  },
  {
    type: 'ClassCastException',
    severity: 'high',
    description: '类型转换异常',
    commonCauses: [
      '强制类型转换错误',
      '泛型类型不匹配',
      '继承关系错误'
    ],
    suggestedFixes: [
      '使用 instanceof 检查',
      '检查泛型类型',
      '修正类型转换'
    ]
  },
  {
    type: 'IllegalArgumentException',
    severity: 'medium',
    description: '非法参数异常',
    commonCauses: [
      '参数值不合法',
      '参数类型错误',
      '参数范围超出'
    ],
    suggestedFixes: [
      '添加参数验证',
      '检查参数类型',
      '验证参数范围'
    ]
  },
  {
    type: 'IOException',
    severity: 'high',
    description: '输入输出异常',
    commonCauses: [
      '文件读写失败',
      '网络连接断开',
      '资源未关闭'
    ],
    suggestedFixes: [
      '使用 try-with-resources',
      '添加异常处理',
      '检查资源状态'
    ]
  },
  // Go 错误
  {
    type: 'panic',
    severity: 'critical',
    description: 'Go panic 运行时错误',
    commonCauses: [
      '数组越界',
      'nil 指针解引用',
      '类型断言失败'
    ],
    suggestedFixes: [
      '使用 defer + recover',
      '添加边界检查',
      '使用 type assertion 检查'
    ]
  },
  {
    type: 'nil pointer dereference',
    severity: 'critical',
    description: 'Go 空指针解引用',
    commonCauses: [
      '未初始化指针',
      '函数返回 nil',
      'map 未初始化'
    ],
    suggestedFixes: [
      '检查指针是否为 nil',
      '使用 make() 初始化 map',
      '添加 nil 检查'
    ]
  },
  // Rust 错误
  {
    type: 'unwrap on None',
    severity: 'critical',
    description: 'Rust Option::unwrap() 在 None 上调用',
    commonCauses: [
      'Option 为 None',
      'Result 为 Err',
      '未处理错误情况'
    ],
    suggestedFixes: [
      '使用 match 处理',
      '使用 unwrap_or()',
      '使用 ? 运算符'
    ]
  },
  {
    type: 'unwrap on Err',
    severity: 'critical',
    description: 'Rust Result::unwrap() 在 Err 上调用',
    commonCauses: [
      'IO 操作失败',
      '解析错误',
      '网络请求失败'
    ],
    suggestedFixes: [
      '使用 match 处理 Result',
      '使用 unwrap_or_else()',
      '传播错误 ?'
    ]
  },
  {
    type: 'index out of bounds',
    severity: 'high',
    description: 'Rust 数组/向量索引越界',
    commonCauses: [
      '索引超出长度',
      '空向量访问',
      '循环条件错误'
    ],
    suggestedFixes: [
      '使用 get() 安全访问',
      '检查长度',
      '使用迭代器'
    ]
  },
  // 网络错误
  {
    type: 'ENOTFOUND',
    severity: 'high',
    description: '网络错误,无法解析域名',
    commonCauses: [
      'DNS 配置错误',
      '网络连接问题',
      '域名拼写错误'
    ],
    suggestedFixes: [
      '检查网络连接',
      '验证域名拼写',
      '检查 DNS 配置'
    ]
  },
  {
    type: 'ECONNREFUSED',
    severity: 'high',
    description: '连接被拒绝,目标服务未启动或端口错误',
    commonCauses: [
      '服务未启动',
      '端口号错误',
      '防火墙阻止'
    ],
    suggestedFixes: [
      '启动目标服务',
      '检查端口配置',
      '检查防火墙规则'
    ]
  },
  {
    type: 'ETIMEDOUT',
    severity: 'high',
    description: '连接超时',
    commonCauses: [
      '服务器响应慢',
      '网络延迟',
      '服务器未响应'
    ],
    suggestedFixes: [
      '增加超时时间',
      '添加重试机制',
      '检查服务器状态'
    ]
  },
  {
    type: 'ECONNRESET',
    severity: 'high',
    description: '连接被重置',
    commonCauses: [
      '服务器断开连接',
      '网络中断',
      '超时被强制断开'
    ],
    suggestedFixes: [
      '添加重连机制',
      '检查网络稳定性',
      '增加超时时间'
    ]
  },
  {
    type: 'EACCES',
    severity: 'high',
    description: '权限被拒绝',
    commonCauses: [
      '文件权限不足',
      '端口被占用',
      '用户权限不够'
    ],
    suggestedFixes: [
      '检查文件权限',
      '使用 sudo 运行',
      '更换端口'
    ]
  },
  {
    type: 'EEXIST',
    severity: 'medium',
    description: '文件已存在',
    commonCauses: [
      '重复创建文件',
      '目录已存在',
      '未检查文件存在性'
    ],
    suggestedFixes: [
      '检查文件是否存在',
      '使用 flag 覆盖',
      '删除旧文件'
    ]
  },
  // PHP 错误
  {
    type: 'Fatal error',
    severity: 'critical',
    description: 'PHP 致命错误,脚本终止执行',
    commonCauses: [
      '调用未定义函数',
      '类未找到',
      '内存耗尽'
    ],
    suggestedFixes: [
      '检查函数/类定义',
      '增加 memory_limit',
      '检查 autoload'
    ]
  },
  {
    type: 'Warning',
    severity: 'medium',
    description: 'PHP 警告,脚本继续执行',
    commonCauses: [
      '参数类型不匹配',
      '文件未找到',
      '除以零'
    ],
    suggestedFixes: [
      '检查参数类型',
      '验证文件路径',
      '添加边界检查'
    ]
  },
  {
    type: 'Notice',
    severity: 'low',
    description: 'PHP 通知,潜在问题',
    commonCauses: [
      '未定义变量',
      '未定义索引',
      '类型转换'
    ],
    suggestedFixes: [
      '初始化变量',
      '使用 isset() 检查',
      '启用严格模式'
    ]
  },
];

/**
 * 匹配错误模式
 */
export function matchErrorPattern(errorMessage: string): ErrorPattern {
  const errorLower = errorMessage.toLowerCase();
  
  for (const pattern of ERROR_PATTERNS) {
    if (errorLower.includes(pattern.type.toLowerCase())) {
      return pattern;
    }
  }
  
  // 返回默认的未知错误模式
  return {
    type: 'UnknownError',
    severity: 'medium',
    description: '未识别的错误类型',
    commonCauses: ['未知错误,需要手动分析'],
    suggestedFixes: ['检查错误消息和堆栈追踪,手动定位问题']
  };
}

/**
 * 解析堆栈追踪
 */
export function analyzeStackTrace(stackTrace: string): BugLocationInternal | null {
  if (!stackTrace) return null;
  
  const lines = stackTrace.split('\n');
  
  for (const line of lines) {
    // TypeScript/JavaScript 堆栈格式
    // at functionName (filePath:line:column)
    const jsMatch = line.match(/at\s+(?:.+?\s+)?\(?([^\s:]+):(\d+):(\d+)\)?/);
    if (jsMatch) {
      return {
        file: jsMatch[1],
        line: parseInt(jsMatch[2], 10),
        column: parseInt(jsMatch[3], 10)
      };
    }
    
    // Python 堆栈格式
    // File "filePath", line N, in function
    const pyMatch = line.match(/File\s+"([^"]+)",\s+line\s+(\d+)/);
    if (pyMatch) {
      return {
        file: pyMatch[1],
        line: parseInt(pyMatch[2], 10)
      };
    }
    
    // Java 堆栈格式
    // at className.methodName(FileName.java:line)
    const javaMatch = line.match(/at\s+[\w.]+\(([\w.]+):(\d+)\)/);
    if (javaMatch) {
      return {
        file: javaMatch[1],
        line: parseInt(javaMatch[2], 10)
      };
    }
  }
  
  return null;
}

/**
 * 生成修复建议(启发式)
 */
export function generateFixSuggestion(
  error: string,
  location?: BugLocationInternal,
  sourceCode?: string
): { suggestion: string; confidence: number } {
  const pattern = matchErrorPattern(error);
  
  if (!pattern) {
    return {
      suggestion: '无法自动识别错误模式,建议手动检查代码',
      confidence: 0.2
    };
  }
  
  // 根据错误类型生成具体建议
  let suggestion = '';
  let confidence = 0.7;
  
  if (pattern.type === 'TypeError' && error.includes('undefined')) {
    suggestion = `检测到 TypeError(undefined)。建议:\n1. 在访问属性前检查对象是否存在\n2. 使用可选链操作符: obj?.prop\n3. 添加默认值: obj.prop || defaultValue`;
    confidence = 0.85;
  } else if (pattern.type === 'ReferenceError') {
    suggestion = `检测到 ReferenceError。建议:\n1. 检查变量名拼写\n2. 确认变量已声明\n3. 检查 import 语句是否完整`;
    confidence = 0.8;
  } else if (pattern.type === 'SyntaxError') {
    suggestion = `检测到 SyntaxError。建议:\n1. 检查括号、引号是否匹配\n2. 运行 ESLint/Prettier 格式化\n3. 检查是否有语法拼写错误`;
    confidence = 0.75;
  } else {
    suggestion = `检测到 ${pattern.type}。建议:\n${pattern.suggestedFixes.map((fix, i) => `${i + 1}. ${fix}`).join('\n')}`;
    confidence = 0.7;
  }
  
  // 如果有源代码,可以提供更具体的建议
  if (sourceCode && location) {
    const lines = sourceCode.split('\n');
    if (location.line > 0 && location.line <= lines.length) {
      const errorLine = lines[location.line - 1];
      suggestion += `\n\n问题代码(第 ${location.line} 行):\n${errorLine.trim()}`;
      confidence += 0.1;
    }
  }
  
  return { suggestion, confidence: Math.min(confidence, 1.0) };
}

/**
 * 生成验证测试用例
 */
export function generateTestCases(
  fix: { suggestion: string; confidence: number },
  errorType: string
): string[] {
  const testCases: string[] = [];
  
  if (errorType.includes('TypeError')) {
    testCases.push(
      '测试 1: 传入 null 或 undefined,验证是否正确处理',
      '测试 2: 传入空对象 {},验证是否正常执行',
      '测试 3: 传入完整对象,验证功能正常'
    );
  } else if (errorType.includes('IndexError') || errorType.includes('RangeError')) {
    testCases.push(
      '测试 1: 访问索引 0,验证边界情况',
      '测试 2: 访问最后一个元素 (array.length - 1)',
      '测试 3: 访问越界索引 (array.length),验证错误处理'
    );
  } else if (errorType.includes('ENOTFOUND') || errorType.includes('ECONNREFUSED')) {
    testCases.push(
      '测试 1: 使用正确的 URL/端口,验证连接成功',
      '测试 2: 使用错误的 URL/端口,验证错误处理',
      '测试 3: 网络断开情况下的超时处理'
    );
  } else {
    testCases.push(
      '测试 1: 正常输入,验证功能正确',
      '测试 2: 边界值输入,验证鲁棒性',
      '测试 3: 异常输入,验证错误处理'
    );
  }
  
  return testCases;
}

/**
 * 诊断 Bug
 * 
 * @param errorMessage 错误消息
 * @param stackTrace 堆栈追踪
 * @param options 诊断选项
 * @returns 诊断结果
 */
export async function diagnoseBug(
  errorMessage: string,
  stackTrace: string,
  options?: BugDiagnosisOptions
): Promise<BugDiagnosisResult> {
  // 生成缓存键
  const cacheKey = `${errorMessage}:${stackTrace}:${options?.sourceCode || ''}`.slice(0, 500);
  
  // 检查缓存
  const cached = diagnosisCache.get(cacheKey);
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
    return cached.result;
  }
  
  // 1. 错误模式匹配
  const pattern = matchErrorPattern(errorMessage);
  
  // 2. 堆栈分析定位问题
  const location = analyzeStackTrace(stackTrace);
  
  // 3. 生成修复建议
  const fix = generateFixSuggestion(errorMessage, location || undefined, options?.sourceCode);
  
  // 4. 生成验证测试用例
  const testCases = generateTestCases(fix, errorMessage);
  
  // 5. 提取相关文件
  const relatedFiles: string[] = [];
  if (location?.file) {
    relatedFiles.push(location.file);
  }
  
  const result: BugDiagnosisResult = {
    errorType: pattern?.type || 'Unknown',
    rootCause: pattern?.description || errorMessage,
    severity: pattern?.severity || 'medium',
    location: location || undefined,
    suggestedFix: fix.suggestion,
    relatedFiles,
    testCases,
    confidence: fix.confidence,
    errorPattern: pattern || undefined
  };
  
  // 写入缓存
  diagnosisCache.set(cacheKey, { result, timestamp: Date.now() });
  
  return result;
}

// 导出测试用例生成器
export { generateTestCasesForError, generateTestFileContent } from './test-generator.js';
export type { TestCase, TestSuite, TestFramework } from './test-generator.js';

/**
 * 生成诊断报告
 */
export function generateDiagnosisReport(result: BugDiagnosisResult): string {
  const parts: string[] = [];
  
  parts.push(`## 🔍 Bug 诊断报告`);
  parts.push(``);
  parts.push(`### 错误类型: ${result.errorType}`);
  parts.push(`**严重程度**: ${'🔴'.repeat(result.severity === 'critical' ? 4 : result.severity === 'high' ? 3 : result.severity === 'medium' ? 2 : 1)} ${result.severity}`);
  parts.push(`**置信度**: ${(result.confidence * 100).toFixed(0)}%`);
  parts.push(``);
  
  parts.push(`### 根因分析`);
  parts.push(result.rootCause);
  parts.push(``);
  
  if (result.location) {
    parts.push(`### 错误位置`);
    parts.push(`- **文件**: ${result.location.file}`);
    parts.push(`- **行号**: ${result.location.line}`);
    if (result.location.column) {
      parts.push(`- **列号**: ${result.location.column}`);
    }
    parts.push(``);
  }
  
  parts.push(`### 修复建议`);
  parts.push(result.suggestedFix);
  parts.push(``);
  
  if (result.relatedFiles.length > 0) {
    parts.push(`### 相关文件`);
    result.relatedFiles.forEach(file => {
      parts.push(`- ${file}`);
    });
    parts.push(``);
  }
  
  if (result.testCases.length > 0) {
    parts.push(`### 验证测试用例`);
    result.testCases.forEach(testCase => {
      parts.push(`- ${testCase}`);
    });
    parts.push(``);
  }
  
  if (result.errorPattern?.commonCauses) {
    parts.push(`### 常见原因`);
    result.errorPattern.commonCauses.forEach((cause, i) => {
      parts.push(`${i + 1}. ${cause}`);
    });
    parts.push(``);
  }
  
  return parts.join('\n');
}
