/**
 * 数据库连接监控工具
 * @file db-monitor.js
 * @description 实时监控数据库连接状态和性能
 */
const { monitorPool, testConnection, resetPool, optimizePool } = require('../config/database-pool');
const queryOptimizer = require('./query-optimizer');
const EventEmitter = require('events');
const fs = require('fs');
const path = require('path');

// 创建事件发射器
class DatabaseEventEmitter extends EventEmitter {}
const dbEvents = new DatabaseEventEmitter();

// 数据库监控类
class DatabaseMonitor {
  constructor() {
    this.isMonitoring = false;
    this.monitorInterval = null;
    this.monitorIntervalTime = 60000; // 默认每分钟监控一次
    this.listeners = [];
    this.status = {
      lastCheck: null,
      isConnected: false,
      poolStats: null,
      slowQueries: [],
      errors: [],
      metrics: {}
    };
    this.logPath = path.join(process.cwd(), 'logs', 'db-monitor');
    this.alertThresholds = {
      connectionErrors: 3,        // 连续连接错误次数阈值
      slowQueryPercentage: 10,    // 慢查询百分比阈值
      connectionPoolUsage: 80,    // 连接池使用率阈值（百分比）
      queryResponseTime: 1000     // 查询响应时间阈值（毫秒）
    };
    this.metricsHistory = {
      connectionPool: [],
      queryPerformance: [],
      errors: []
    };
    this.maxMetricsHistory = 100; // 保存最近100条历史记录
    
    // 确保日志目录存在
    this.ensureLogDirectory();
  }

  // 确保日志目录存在
  ensureLogDirectory() {
    try {
      if (!fs.existsSync(path.join(process.cwd(), 'logs'))) {
        fs.mkdirSync(path.join(process.cwd(), 'logs'));
      }
      if (!fs.existsSync(this.logPath)) {
        fs.mkdirSync(this.logPath);
      }
    } catch (error) {
      console.error('创建日志目录失败:', error);
    }
  }

  // 开始监控
  startMonitoring(intervalTime = this.monitorIntervalTime) {
    if (this.isMonitoring) {
      return false;
    }

    this.monitorIntervalTime = intervalTime;
    this.isMonitoring = true;

    // 立即执行一次监控
    this.checkStatus();

    // 设置定时监控
    this.monitorInterval = setInterval(() => {
      this.checkStatus();
    }, this.monitorIntervalTime);

    console.log(`数据库监控已启动，监控间隔: ${this.monitorIntervalTime}ms`);
    dbEvents.emit('monitoring_started', { interval: this.monitorIntervalTime });
    return true;
  }

  // 停止监控
  stopMonitoring() {
    if (!this.isMonitoring) {
      return false;
    }

    clearInterval(this.monitorInterval);
    this.monitorInterval = null;
    this.isMonitoring = false;

    console.log('数据库监控已停止');
    dbEvents.emit('monitoring_stopped');
    return true;
  }

  // 检查数据库状态
  async checkStatus() {
    try {
      // 检查连接
      const isConnected = await testConnection();
      
      // 获取连接池状态
      const poolStats = monitorPool();
      
      // 获取慢查询
      const slowQueries = await queryOptimizer.identifySlowQueries(this.alertThresholds.queryResponseTime);
      
      // 获取数据库状态
      const dbStatus = await queryOptimizer.getDatabaseStatus();
      
      // 计算指标
      const metrics = this.calculateMetrics(isConnected, poolStats, slowQueries, dbStatus);
      
      // 更新状态
      this.status = {
        lastCheck: new Date(),
        isConnected,
        poolStats,
        slowQueries,
        errors: isConnected ? [] : [{ time: new Date(), message: '数据库连接失败' }],
        metrics
      };
      
      // 更新历史记录
      this.updateMetricsHistory(metrics);
      
      // 检查是否需要发出警报
      this.checkAlerts();
      
      // 记录状态日志
      this.logStatus();
      
      // 通知所有监听器
      this.notifyListeners();
      
      // 如果连接失败，记录错误
      if (!isConnected) {
        console.error('数据库连接检查失败');
        this.logError('数据库连接检查失败');
        dbEvents.emit('connection_error', { time: new Date(), message: '数据库连接失败' });
      }
      
      return this.status;
    } catch (error) {
      const errorStatus = {
        lastCheck: new Date(),
        isConnected: false,
        poolStats: null,
        slowQueries: [],
        errors: [{ time: new Date(), message: error.message }],
        metrics: {}
      };
      
      this.status = errorStatus;
      this.logError(error.message);
      this.notifyListeners();
      
      console.error('数据库状态检查失败:', error);
      dbEvents.emit('status_check_error', { time: new Date(), error: error.message });
      return errorStatus;
    }
  }

  // 计算监控指标
  calculateMetrics(isConnected, poolStats, slowQueries, dbStatus) {
    // 连接池使用率
    const poolUsage = poolStats && poolStats.total > 0 
      ? (poolStats.borrowed / poolStats.total) * 100 
      : 0;
    
    // 慢查询百分比
    const totalQueries = dbStatus && dbStatus.queries ? parseInt(dbStatus.queries.total) || 0 : 0;
    const slowQueryCount = slowQueries ? slowQueries.length : 0;
    const slowQueryPercentage = totalQueries > 0 
      ? (slowQueryCount / totalQueries) * 100 
      : 0;
    
    // 缓冲池命中率
    const bufferPoolHitRate = dbStatus && dbStatus.buffer_pool ? dbStatus.buffer_pool.hit_rate : 0;
    
    return {
      connectionStatus: isConnected ? 'connected' : 'disconnected',
      poolUsage: parseFloat(poolUsage.toFixed(2)),
      slowQueryPercentage: parseFloat(slowQueryPercentage.toFixed(2)),
      bufferPoolHitRate: parseFloat(bufferPoolHitRate.toFixed(2)),
      timestamp: new Date()
    };
  }

  // 更新指标历史记录
  updateMetricsHistory(metrics) {
    // 更新连接池历史
    this.metricsHistory.connectionPool.push({
      timestamp: new Date(),
      poolUsage: metrics.poolUsage,
      connectionStatus: metrics.connectionStatus
    });
    
    // 更新查询性能历史
    this.metricsHistory.queryPerformance.push({
      timestamp: new Date(),
      slowQueryPercentage: metrics.slowQueryPercentage,
      bufferPoolHitRate: metrics.bufferPoolHitRate
    });
    
    // 限制历史记录数量
    if (this.metricsHistory.connectionPool.length > this.maxMetricsHistory) {
      this.metricsHistory.connectionPool.shift();
    }
    
    if (this.metricsHistory.queryPerformance.length > this.maxMetricsHistory) {
      this.metricsHistory.queryPerformance.shift();
    }
    
    if (this.metricsHistory.errors.length > this.maxMetricsHistory) {
      this.metricsHistory.errors.shift();
    }
  }

  // 检查是否需要发出警报
  checkAlerts() {
    const { metrics, slowQueries, poolStats } = this.status;
    
    // 检查连接池使用率
    if (metrics.poolUsage > this.alertThresholds.connectionPoolUsage) {
      const alert = {
        type: 'high_pool_usage',
        message: `连接池使用率过高: ${metrics.poolUsage}%`,
        level: 'warning',
        timestamp: new Date()
      };
      dbEvents.emit('alert', alert);
      console.warn(alert.message);
    }
    
    // 检查慢查询百分比
    if (metrics.slowQueryPercentage > this.alertThresholds.slowQueryPercentage) {
      const alert = {
        type: 'high_slow_query_percentage',
        message: `慢查询百分比过高: ${metrics.slowQueryPercentage}%`,
        level: 'warning',
        timestamp: new Date(),
        details: slowQueries
      };
      dbEvents.emit('alert', alert);
      console.warn(alert.message);
    }
    
    // 检查连接错误
    const recentErrors = this.metricsHistory.errors.slice(-this.alertThresholds.connectionErrors);
    if (recentErrors.length >= this.alertThresholds.connectionErrors) {
      const alert = {
        type: 'connection_errors',
        message: `连续出现${recentErrors.length}次连接错误`,
        level: 'error',
        timestamp: new Date(),
        details: recentErrors
      };
      dbEvents.emit('alert', alert);
      console.error(alert.message);
    }
  }

  // 记录状态日志
  logStatus() {
    try {
      const logFile = path.join(this.logPath, `status-${new Date().toISOString().split('T')[0]}.log`);
      const logData = JSON.stringify({
        timestamp: new Date(),
        status: this.status
      }) + '\n';
      
      fs.appendFileSync(logFile, logData);
    } catch (error) {
      console.error('记录状态日志失败:', error);
    }
  }

  // 记录错误日志
  logError(message) {
    try {
      const errorLog = {
        timestamp: new Date(),
        message
      };
      
      // 添加到错误历史
      this.metricsHistory.errors.push(errorLog);
      
      // 写入错误日志文件
      const logFile = path.join(this.logPath, `error-${new Date().toISOString().split('T')[0]}.log`);
      const logData = JSON.stringify(errorLog) + '\n';
      
      fs.appendFileSync(logFile, logData);
    } catch (error) {
      console.error('记录错误日志失败:', error);
    }
  }

  // 获取当前状态
  getStatus() {
    return this.status;
  }

  // 获取历史指标
  getMetricsHistory() {
    return this.metricsHistory;
  }

  // 添加状态变化监听器
  addListener(listener) {
    if (typeof listener === 'function' && !this.listeners.includes(listener)) {
      this.listeners.push(listener);
      return true;
    }
    return false;
  }

  // 移除监听器
  removeListener(listener) {
    const index = this.listeners.indexOf(listener);
    if (index !== -1) {
      this.listeners.splice(index, 1);
      return true;
    }
    return false;
  }

  // 通知所有监听器
  notifyListeners() {
    this.listeners.forEach(listener => {
      try {
        listener(this.status);
      } catch (error) {
        console.error('监听器执行失败:', error);
      }
    });
  }

  // 设置监控间隔
  setMonitorInterval(intervalTime) {
    if (intervalTime < 1000) {
      console.warn('监控间隔不能小于1000ms，已设置为1000ms');
      intervalTime = 1000;
    }

    this.monitorIntervalTime = intervalTime;

    // 如果正在监控，重新启动监控
    if (this.isMonitoring) {
      this.stopMonitoring();
      this.startMonitoring();
    }

    return this.monitorIntervalTime;
  }

  // 设置警报阈值
  setAlertThresholds(thresholds = {}) {
    this.alertThresholds = {
      ...this.alertThresholds,
      ...thresholds
    };
    return this.alertThresholds;
  }

  // 获取警报阈值
  getAlertThresholds() {
    return this.alertThresholds;
  }

  // 优化连接池
  async optimizeConnectionPool() {
    try {
      // 获取当前连接池状态
      const poolStats = monitorPool();
      
      // 根据当前使用情况计算优化配置
      const newConfig = {};
      
      // 如果连接池使用率超过80%，增加最大连接数
      if (poolStats.borrowed / poolStats.total > 0.8) {
        newConfig.max = Math.min(poolStats.max + 5, 30); // 增加5个连接，但不超过30
      }
      
      // 如果连接池使用率低于20%，减少最大连接数
      if (poolStats.borrowed / poolStats.total < 0.2 && poolStats.max > 10) {
        newConfig.max = Math.max(poolStats.max - 5, 10); // 减少5个连接，但不低于10
      }
      
      // 应用优化配置
      if (Object.keys(newConfig).length > 0) {
        const result = await optimizePool(newConfig);
        console.log('连接池已优化:', result);
        dbEvents.emit('pool_optimized', result);
        return result;
      }
      
      return poolStats;
    } catch (error) {
      console.error('优化连接池失败:', error);
      return { error: error.message };
    }
  }

  // 重置连接池
  async resetConnectionPool() {
    try {
      const result = await resetPool();
      console.log('连接池已重置:', result);
      dbEvents.emit('pool_reset', result);
      return result;
    } catch (error) {
      console.error('重置连接池失败:', error);
      return { error: error.message };
    }
  }

  // 获取详细的数据库信息
  async getDatabaseInfo() {
    try {
      // 获取数据库状态
      const dbStatus = await queryOptimizer.getDatabaseStatus();
      
      // 获取当前连接池状态
      const poolStats = monitorPool();
      
      // 获取慢查询
      const slowQueries = await queryOptimizer.identifySlowQueries();
      
      // 获取表信息
      const tables = await this.getTablesList();
      const tableInfoPromises = tables.map(table => queryOptimizer.getTableInfo(table));
      const tablesInfo = await Promise.all(tableInfoPromises);
      
      return {
        timestamp: new Date(),
        connection: {
          isConnected: await testConnection(),
          pool: poolStats
        },
        performance: {
          slowQueries,
          metrics: this.status.metrics,
          history: this.metricsHistory
        },
        database: dbStatus,
        tables: tablesInfo.reduce((acc, info, index) => {
          acc[tables[index]] = info;
          return acc;
        }, {})
      };
    } catch (error) {
      console.error('获取数据库信息失败:', error);
      return {
        timestamp: new Date(),
        error: error.message,
        connection: { isConnected: false, pool: null },
        performance: { slowQueries: [], metrics: {}, history: {} },
        database: { variables: {}, status: {} },
        tables: {}
      };
    }
  }

  // 获取表列表
  async getTablesList() {
    try {
      const result = await sequelize.query(
        'SHOW TABLES',
        { type: sequelize.QueryTypes.SHOWTABLES }
      );
      
      // 结果格式可能因数据库类型而异
      return Array.isArray(result) 
        ? result.flat().filter(Boolean)
        : [];
    } catch (error) {
      console.error('获取表列表失败:', error);
      return [];
    }
  }
}

// 创建数据库监控实例
const dbMonitor = new DatabaseMonitor();

// 导出事件发射器，允许外部监听事件
dbMonitor.events = dbEvents;

module.exports = dbMonitor;