/**
 * System Health Monitoring Service
 * Tracks server performance, database health, and API metrics
 */

export interface HealthMetrics {
  uptime: number;
  memoryUsage: {
    heapUsed: number;
    heapTotal: number;
    external: number;
    rss: number;
  };
  cpuUsage: {
    user: number;
    system: number;
  };
  database: {
    connected: boolean;
    responseTime: number;
    queryCount: number;
  };
  api: {
    requestCount: number;
    errorCount: number;
    averageResponseTime: number;
    p95ResponseTime: number;
  };
  status: 'healthy' | 'degraded' | 'critical';
}

class SystemHealthService {
  private startTime = Date.now();
  private requestMetrics: number[] = [];
  private errorCount = 0;
  private requestCount = 0;
  private lastCpuUsage = process.cpuUsage();
  private lastCpuTime = Date.now();

  /**
   * Get current system health metrics
   */
  getHealthMetrics(): HealthMetrics {
    const memUsage = process.memoryUsage();
    const cpuUsage = this.calculateCpuUsage();
    const uptime = (Date.now() - this.startTime) / 1000;

    // Calculate API metrics
    const avgResponseTime =
      this.requestMetrics.length > 0
        ? this.requestMetrics.reduce((a, b) => a + b, 0) / this.requestMetrics.length
        : 0;

    const sortedMetrics = [...this.requestMetrics].sort((a, b) => a - b);
    const p95Index = Math.floor(sortedMetrics.length * 0.95);
    const p95ResponseTime = sortedMetrics[p95Index] || 0;

    // Determine overall status
    let status: 'healthy' | 'degraded' | 'critical' = 'healthy';

    if (memUsage.heapUsed / memUsage.heapTotal > 0.9) {
      status = 'critical';
    } else if (memUsage.heapUsed / memUsage.heapTotal > 0.75) {
      status = 'degraded';
    }

    if (this.errorCount > this.requestCount * 0.05) {
      status = 'degraded';
    }

    if (avgResponseTime > 5000) {
      status = 'degraded';
    }

    return {
      uptime,
      memoryUsage: {
        heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024),
        heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
        external: Math.round(memUsage.external / 1024 / 1024),
        rss: Math.round(memUsage.rss / 1024 / 1024),
      },
      cpuUsage,
      database: {
        connected: true, // TODO: Add actual database connection check
        responseTime: 50, // TODO: Add actual database query timing
        queryCount: 0, // TODO: Add actual query count tracking
      },
      api: {
        requestCount: this.requestCount,
        errorCount: this.errorCount,
        averageResponseTime: Math.round(avgResponseTime),
        p95ResponseTime: Math.round(p95ResponseTime),
      },
      status,
    };
  }

  /**
   * Record API request metrics
   */
  recordRequest(responseTime: number, success: boolean): void {
    this.requestMetrics.push(responseTime);
    this.requestCount++;

    if (!success) {
      this.errorCount++;
    }

    // Keep only last 1000 metrics to avoid memory bloat
    if (this.requestMetrics.length > 1000) {
      this.requestMetrics = this.requestMetrics.slice(-1000);
    }
  }

  /**
   * Calculate CPU usage percentage
   */
  private calculateCpuUsage(): { user: number; system: number } {
    const cpuUsage = process.cpuUsage(this.lastCpuUsage);
    const timeDiff = Date.now() - this.lastCpuTime;

    // Convert microseconds to milliseconds and calculate percentage
    const userPercent = (cpuUsage.user / 1000) / timeDiff * 100;
    const systemPercent = (cpuUsage.system / 1000) / timeDiff * 100;

    this.lastCpuUsage = process.cpuUsage();
    this.lastCpuTime = Date.now();

    return { user: userPercent, system: systemPercent };
  }
}
