import fs from 'fs';
import path from 'path';

// 日志级别枚举
export enum LogLevel {
  DEBUG = 'DEBUG',
  INFO = 'INFO',
  WARN = 'WARN',
  ERROR = 'ERROR',
}

// 请求日志结构
export interface RequestLog {
  requestId: string;
  timestamp: Date;
  method: string;
  path: string;
  query: string;
  status: number;
  responseTime: number;
  responseSize: number;
  level: LogLevel;
  error?: string;
  stack?: string;
  headers: Record<string, string>;
  ip: string;
  userAgent: string;
  body?: any;
}

// 错误分析结果
export interface ErrorAnalysis {
  errorType: string;
  errorMessage: string;
  count: number;
  lastOccurrence: Date;
  paths: string[];
  solutions: string[];
}

// 日志服务类
export class LogService {
  private logs: RequestLog[] = [];
  private maxLogs: number = 10000;
  private logFilePath: string;
  private errorPatterns: Map<string, RegExp> = new Map();
  private errorSolutions: Map<string, string[]> = new Map();

  constructor() {
    this.logFilePath = path.join(process.cwd(), 'logs', 'requests.json');

    // 确保日志目录存在
    const logDir = path.dirname(this.logFilePath);
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true });
    }

    // 初始化错误模式和解决方案
    this.initializeErrorPatterns();

    // 从文件加载历史日志
    this.loadLogs();
  }

  // 初始化常见错误模式
  private initializeErrorPatterns(): void {
    // 数据库连接错误
    this.errorPatterns.set('DB_CONNECTION', /ECONNREFUSED|ER_ACCESS_DENIED_ERROR|Connection refused/);
    this.errorSolutions.set('DB_CONNECTION', [
      '检查MySQL服务是否启动',
      '检查数据库连接配置是否正确',
      '确认数据库用户权限'
    ]);

    // JSON解析错误
    this.errorPatterns.set('JSON_PARSE', /JSON\.parse|SyntaxError|Unexpected token/);
    this.errorSolutions.set('JSON_PARSE', [
      '检查请求body格式是否为有效JSON',
      '确认Content-Type为application/json'
    ]);

    // 参数验证错误
    this.errorPatterns.set('VALIDATION', /validation|is required|invalid parameter/);
    this.errorSolutions.set('VALIDATION', [
      '检查请求参数是否完整',
      '验证参数类型是否正确'
    ]);

    // 文件不存在错误
    this.errorPatterns.set('FILE_NOT_FOUND', /ENOENT|no such file|not found/);
    this.errorSolutions.set('FILE_NOT_FOUND', [
      '检查文件路径是否正确',
      '确认文件是否已上传'
    ]);

    // 权限错误
    this.errorPatterns.set('PERMISSION', /EACCES|permission denied|Unauthorized/);
    this.errorSolutions.set('PERMISSION', [
      '检查用户权限设置',
      '确认登录状态是否有效'
    ]);

    // 超时错误
    this.errorPatterns.set('TIMEOUT', /ETIMEDOUT|timeout|TIMEOUT/);
    this.errorSolutions.set('TIMEOUT', [
      '检查网络连接是否稳定',
      '增加请求超时时间',
      '重试请求'
    ]);
  }

  // 加载历史日志
  private loadLogs(): void {
    try {
      if (fs.existsSync(this.logFilePath)) {
        const data = fs.readFileSync(this.logFilePath, 'utf-8');
        const logs = JSON.parse(data);
        this.logs = logs.map((log: any) => ({
          ...log,
          timestamp: new Date(log.timestamp)
        }));
        console.log(`📋 已加载 ${this.logs.length} 条历史日志`);
      }
    } catch (error) {
      console.error('加载日志文件失败:', error);
    }
  }

  // 保存日志到文件
  private saveLogs(): void {
    try {
      // 只保存最近的日志
      const logsToSave = this.logs.slice(-this.maxLogs);
      fs.writeFileSync(this.logFilePath, JSON.stringify(logsToSave, null, 2));
    } catch (error) {
      console.error('保存日志文件失败:', error);
    }
  }

  // 记录请求日志
  logRequest(log: RequestLog): void {
    log.timestamp = new Date();

    // 添加到内存日志
    this.logs.push(log);

    // 超过最大数量时移除旧日志
    if (this.logs.length > this.maxLogs) {
      this.logs = this.logs.slice(-this.maxLogs);
    }

    // 异步保存到文件
    setTimeout(() => this.saveLogs(), 100);

    // 控制台输出
    const levelEmoji = {
      [LogLevel.DEBUG]: '🔍',
      [LogLevel.INFO]: '📝',
      [LogLevel.WARN]: '⚠️',
      [LogLevel.ERROR]: '❌'
    };

    console.log(
      `${levelEmoji[log.level]} [${log.level}] ${log.method} ${log.path} - ${log.status} (${log.responseTime}ms)`
    );

    // 错误日志额外输出错误信息
    if (log.error) {
      console.error(`   Error: ${log.error}`);
    }
  }

  // 获取所有日志
  getLogs(filter?: {
    level?: LogLevel;
    path?: string;
    status?: number;
    startTime?: Date;
    endTime?: Date;
  }): RequestLog[] {
    let result = [...this.logs];

    if (filter) {
      if (filter.level) {
        result = result.filter(log => log.level === filter.level);
      }
      if (filter.path) {
        result = result.filter(log => log.path.includes(filter.path));
      }
      if (filter.status) {
        result = result.filter(log => log.status === filter.status);
      }
      if (filter.startTime) {
        result = result.filter(log => log.timestamp >= filter.startTime);
      }
      if (filter.endTime) {
        result = result.filter(log => log.timestamp <= filter.endTime);
      }
    }

    return result;
  }

  // 获取错误日志
  getErrorLogs(): RequestLog[] {
    return this.logs.filter(log => log.level === LogLevel.ERROR);
  }

  // 获取最近N条错误日志
  getRecentErrors(count: number = 10): RequestLog[] {
    return this.logs
      .filter(log => log.level === LogLevel.ERROR)
      .slice(-count)
      .reverse();
  }

  // 分析错误模式
  analyzeErrors(): ErrorAnalysis[] {
    const errorLogs = this.getErrorLogs();
    const analyses: Map<string, ErrorLogGroup> = new Map();

    interface ErrorLogGroup {
      errorType: string;
      errorMessage: string;
      count: number;
      lastOccurrence: Date;
      paths: Set<string>;
    }

    for (const log of errorLogs) {
      if (!log.error) continue;

      // 匹配错误类型
      let matchedType = 'UNKNOWN';
      let matchedMessage = log.error;

      for (const [type, pattern] of this.errorPatterns) {
        if (pattern.test(log.error)) {
          matchedType = type;
          break;
        }
      }

      const key = `${matchedType}:${log.error.substring(0, 100)}`;

      if (!analyses.has(key)) {
        analyses.set(key, {
          errorType: matchedType,
          errorMessage: log.error,
          count: 0,
          lastOccurrence: log.timestamp,
          paths: new Set()
        });
      }

      const group = analyses.get(key)!;
      group.count++;
      group.lastOccurrence = log.timestamp;
      group.paths.add(log.path);
    }

    // 转换为结果数组
    return Array.from(analyses.values()).map(group => ({
      errorType: group.errorType,
      errorMessage: group.errorMessage,
      count: group.count,
      lastOccurrence: group.lastOccurrence,
      paths: Array.from(group.paths),
      solutions: this.errorSolutions.get(group.errorType) || ['请查看错误日志获取更多信息']
    }));
  }

  // 自动分析并提供修复建议
  autoAnalyzeError(errorLog: RequestLog): string[] {
    if (!errorLog.error) return ['没有错误信息'];

    const suggestions: string[] = [];

    // 检查是否匹配已知错误模式
    for (const [type, pattern] of this.errorPatterns) {
      if (pattern.test(errorLog.error)) {
        const solutions = this.errorSolutions.get(type);
        if (solutions) {
          suggestions.push(...solutions);
        }
      }
    }

    // 如果没有匹配的模式，提供通用建议
    if (suggestions.length === 0) {
      suggestions.push('检查错误日志了解详细信息');
      suggestions.push('查看相关代码逻辑');
      suggestions.push('尝试重新请求');
    }

    return suggestions;
  }

  // 清除旧日志
  clearLogs(olderThanHours?: number): number {
    const now = new Date();
    let initialCount = this.logs.length;

    if (olderThanHours) {
      const cutoffTime = new Date(now.getTime() - olderThanHours * 60 * 60 * 1000);
      this.logs = this.logs.filter(log => log.timestamp >= cutoffTime);
    } else {
      this.logs = [];
    }

    const removed = initialCount - this.logs.length;
    this.saveLogs();

    return removed;
  }

  // 获取统计数据
  getStats(): {
    total: number;
    errors: number;
    warnings: number;
    averageResponseTime: number;
    topPaths: Array<{ path: string; count: number }>;
  } {
    const stats = {
      total: this.logs.length,
      errors: this.logs.filter(l => l.level === LogLevel.ERROR).length,
      warnings: this.logs.filter(l => l.level === LogLevel.WARN).length,
      averageResponseTime: 0,
      topPaths: [] as Array<{ path: string; count: number }>
    };

    if (this.logs.length > 0) {
      const totalResponseTime = this.logs.reduce((sum, log) => sum + log.responseTime, 0);
      stats.averageResponseTime = Math.round(totalResponseTime / this.logs.length);
    }

    // 统计最常访问的路径
    const pathCounts = new Map<string, number>();
    for (const log of this.logs) {
      pathCounts.set(log.path, (pathCounts.get(log.path) || 0) + 1);
    }

    stats.topPaths = Array.from(pathCounts.entries())
      .map(([path, count]) => ({ path, count }))
      .sort((a, b) => b.count - a.count)
      .slice(0, 10);

    return stats;
  }
}

// 导出单例
export const logService = new LogService();