import { getDatabaseConnectionCount } from '../../config/database.js'
import { logger } from '../logging/logger.js'

/**
 * 监控指标类
 * 
 * 提供关键指标的收集和监控能力：
 * - 数据库连接数监控
 * - 内存使用监控
 * - API响应时间监控
 * - 错误率监控
 * 
 * @example
 * ```typescript
 * import { Metrics } from '@/common/monitoring'
 * 
 * // 记录数据库连接数
 * await Metrics.recordDBConnectionCount()
 * 
 * // 记录API响应时间
 * Metrics.recordAPIResponseTime('GET', '/api/projects', 200, 150)
 * 
 * // 记录错误
 * Metrics.recordError('DatabaseError', 'Connection timeout')
 * ```
 */
export class Metrics {
  /**
   * 记录数据库连接数
   * 
   * 如果连接数超过阈值，会记录警告日志
   * 
   * @param warnThreshold 警告阈值（百分比，默认80）
   * @param errorThreshold 错误阈值（百分比，默认90）
   */
  static async recordDBConnectionCount(
    warnThreshold: number = 80,
    errorThreshold: number = 90
  ): Promise<number> {
    try {
      const count = await getDatabaseConnectionCount()
      const maxConnections = Number(process.env.DB_MAX_CONNECTIONS) || 400
      const usagePercent = (count / maxConnections) * 100

      // 记录指标
      logger.info('Database connection count', {
        type: 'metric',
        metric: 'db.connections',
        value: count,
        max: maxConnections,
        usagePercent: Math.round(usagePercent)
      })

      // 告警逻辑
      if (usagePercent >= errorThreshold) {
        logger.error('Database connection pool near exhaustion', {
          type: 'alert',
          severity: 'critical',
          metric: 'db.connections',
          current: count,
          max: maxConnections,
          usagePercent: Math.round(usagePercent)
        })
      } else if (usagePercent >= warnThreshold) {
        logger.warn('Database connection pool usage high', {
          type: 'alert',
          severity: 'warning',
          metric: 'db.connections',
          current: count,
          max: maxConnections,
          usagePercent: Math.round(usagePercent)
        })
      }

      return count
    } catch (error: any) {
      logger.error('Failed to record database connection count', {
        type: 'metric_error',
        metric: 'db.connections',
        error: error.message
      })
      return 0
    }
  }

  /**
   * 记录内存使用情况
   * 
   * @param warnThreshold 警告阈值（百分比，默认80）
   */
  static recordMemoryUsage(warnThreshold: number = 80): void {
    const memUsage = process.memoryUsage()
    const heapUsagePercent = (memUsage.heapUsed / memUsage.heapTotal) * 100

    logger.info('Memory usage', {
      type: 'metric',
      metric: 'memory.usage',
      rss: Math.round(memUsage.rss / 1024 / 1024),
      heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
      heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
      heapUsagePercent: Math.round(heapUsagePercent),
      external: Math.round(memUsage.external / 1024 / 1024)
    })

    // 告警
    if (heapUsagePercent >= warnThreshold) {
      logger.warn('High memory usage detected', {
        type: 'alert',
        severity: 'warning',
        metric: 'memory.usage',
        heapUsagePercent: Math.round(heapUsagePercent),
        heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
        heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024)
      })
    }
  }

  /**
   * 记录API响应时间
   * 
   * @param method HTTP方法
   * @param path API路径
   * @param statusCode 状态码
   * @param duration 响应时间（毫秒）
   * @param slowThreshold 慢请求阈值（毫秒，默认1000）
   */
  static recordAPIResponseTime(
    method: string,
    path: string,
    statusCode: number,
    duration: number,
    slowThreshold: number = 1000
  ): void {
    const level = statusCode >= 500 ? 'error' : statusCode >= 400 ? 'warn' : 'info'

    logger.log(level, 'API response', {
      type: 'metric',
      metric: 'api.response_time',
      method,
      path,
      statusCode,
      duration,
      slow: duration >= slowThreshold
    })

    // 慢请求告警
    if (duration >= slowThreshold) {
      logger.warn('Slow API request detected', {
        type: 'alert',
        severity: 'warning',
        metric: 'api.slow_request',
        method,
        path,
        duration,
        threshold: slowThreshold
      })
    }
  }

  /**
   * 记录错误
   * 
   * @param errorType 错误类型
   * @param message 错误消息
   * @param context 上下文信息
   */
  static recordError(
    errorType: string,
    message: string,
    context?: Record<string, any>
  ): void {
    logger.error('Application error', {
      type: 'metric',
      metric: 'app.error',
      errorType,
      message,
      ...context
    })
  }

  /**
   * 记录LLM API调用
   * 
   * @param provider LLM提供商（deepseek、qwen等）
   * @param operation 操作类型（chat、embedding等）
   * @param duration 响应时间（毫秒）
   * @param success 是否成功
   * @param tokens 使用的token数
   */
  static recordLLMCall(
    provider: string,
    operation: string,
    duration: number,
    success: boolean,
    tokens?: { prompt: number; completion: number; total: number }
  ): void {
    logger.info('LLM API call', {
      type: 'metric',
      metric: 'llm.api_call',
      provider,
      operation,
      duration,
      success,
      tokens
    })

    // 失败告警
    if (!success) {
      logger.warn('LLM API call failed', {
        type: 'alert',
        severity: 'warning',
        metric: 'llm.api_failure',
        provider,
        operation,
        duration
      })
    }
  }

  /**
   * 记录异步任务
   * 
   * @param jobType 任务类型
   * @param status 任务状态
   * @param duration 执行时间（毫秒）
   * @param context 上下文信息
   */
  static recordAsyncJob(
    jobType: string,
    status: 'started' | 'completed' | 'failed',
    duration?: number,
    context?: Record<string, any>
  ): void {
    const level = status === 'failed' ? 'error' : 'info'

    logger.log(level, 'Async job', {
      type: 'metric',
      metric: 'job.status',
      jobType,
      status,
      duration,
      ...context
    })
  }

  /**
   * 记录缓存命中率
   * 
   * @param cacheKey 缓存键
   * @param hit 是否命中
   * @param ttl TTL（秒）
   */
  static recordCacheHit(cacheKey: string, hit: boolean, ttl?: number): void {
    logger.debug('Cache access', {
      type: 'metric',
      metric: 'cache.access',
      key: cacheKey,
      hit,
      ttl
    })
  }

  /**
   * 获取系统概览指标
   * 
   * @returns 系统概览
   */
  static async getSystemOverview(): Promise<Record<string, any>> {
    const overview: Record<string, any> = {}

    // 数据库连接数
    try {
      const dbConnections = await getDatabaseConnectionCount()
      const maxConnections = Number(process.env.DB_MAX_CONNECTIONS) || 400
      overview.database = {
        connections: dbConnections,
        maxConnections,
        usagePercent: Math.round((dbConnections / maxConnections) * 100)
      }
    } catch (error) {
      overview.database = { error: 'Failed to fetch' }
    }

    // 内存使用
    const memUsage = process.memoryUsage()
    overview.memory = {
      rss: Math.round(memUsage.rss / 1024 / 1024),
      heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
      heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
      heapUsagePercent: Math.round((memUsage.heapUsed / memUsage.heapTotal) * 100)
    }

    // 进程信息
    overview.process = {
      pid: process.pid,
      uptime: Math.round(process.uptime()),
      version: process.version,
      platform: process.platform
    }

    return overview
  }

  /**
   * 启动定期监控
   * 
   * 每分钟收集一次关键指标
   * 
   * @param intervalMs 监控间隔（毫秒，默认60000）
   * @returns 定时器ID（可用于停止监控）
   */
  static startPeriodicMonitoring(intervalMs: number = 60000): NodeJS.Timeout {
    logger.info('Starting periodic monitoring', { intervalMs })

    const timer = setInterval(async () => {
      // 记录数据库连接数
      await this.recordDBConnectionCount()

      // 记录内存使用
      this.recordMemoryUsage()
    }, intervalMs)

    return timer
  }

  /**
   * 停止定期监控
   * 
   * @param timer 定时器ID
   */
  static stopPeriodicMonitoring(timer: NodeJS.Timeout): void {
    clearInterval(timer)
    logger.info('Stopped periodic monitoring')
  }
}

/**
 * Fastify请求计时中间件
 * 
 * @example
 * ```typescript
 * import { requestTimingHook } from '@/common/monitoring'
 * 
 * app.addHook('onRequest', requestTimingHook)
 * ```
 */
export function requestTimingHook(request: any, _reply: any, done: () => void) {
  request.startTime = Date.now()
  done()
}

/**
 * Fastify响应计时中间件
 * 
 * @example
 * ```typescript
 * import { responseTimingHook } from '@/common/monitoring'
 * 
 * app.addHook('onResponse', responseTimingHook)
 * ```
 */
export function responseTimingHook(request: any, reply: any, done: () => void) {
  if (request.startTime) {
    const duration = Date.now() - request.startTime
    Metrics.recordAPIResponseTime(
      request.method,
      request.url,
      reply.statusCode,
      duration
    )
  }
  done()
}

