import pidusage from 'pidusage';
import { performance } from 'perf_hooks';
import { SystemStats, CpuMetrics, MemoryMetrics } from './types';
import os from 'os';

export class Stats {
  private latestStats: SystemStats;
  private eventLoopLag: number;
  private lastCpuUsage: { user: number; system: number };
  private lastCpuCheck: number;

  constructor() {
    this.eventLoopLag = 0;
    this.lastCpuCheck = Date.now();
    this.lastCpuUsage = process.cpuUsage();
    this.latestStats = {
      timestamp: Date.now(),
      cpu: {
        percentage: '0',
        system: 0,
        user: 0
      },
      memory: {
        heapUsed: 0,
        heapTotal: 0,
        rss: 0,
        external: 0
      },
      eventLoopDelay: 0
    };
    this.startEventLoopMonitoring();
  }

  private startEventLoopMonitoring(): void {
    let lastCheck = performance.now();
    let minLag = Infinity;
    let maxLag = 0;
    let samples = 0;
    let totalLag = 0;
    
    setInterval(() => {
      const now = performance.now();
      const delta = now - lastCheck;
      const lag = Math.max(0, delta - 1);
      
      // Update stats
      minLag = Math.min(minLag, lag);
      maxLag = Math.max(maxLag, lag);
      totalLag += lag;
      samples++;
      
      // Calculate average lag over the last interval
      if (samples >= 10) {  // Average over 10 samples
        this.eventLoopLag = totalLag / samples;
        minLag = Infinity;
        maxLag = 0;
        totalLag = 0;
        samples = 0;
      }
      
      lastCheck = now;
    }, 10);  // Sample every 10ms for better accuracy
  }

  private calculateCpuUsage(): CpuMetrics {
    const now = Date.now();
    const currentCpuUsage = process.cpuUsage();
    const userDiff = currentCpuUsage.user - this.lastCpuUsage.user;
    const systemDiff = currentCpuUsage.system - this.lastCpuUsage.system;
    const timeDiff = now - this.lastCpuCheck;

    this.lastCpuUsage = currentCpuUsage;
    this.lastCpuCheck = now;

    // Convert microseconds to milliseconds
    const totalUsage = (userDiff + systemDiff) / 1000;
    
    // Calculate percentage based on elapsed time and number of cores
    const numCores = os.cpus().length;
    const maxTime = timeDiff * numCores * 1000; // Convert to microseconds
    const percentage = ((totalUsage / maxTime) * 100).toFixed(1);

    return {
      percentage,
      system: systemDiff / 1000000, // Convert to seconds
      user: userDiff / 1000000
    };
  }

  public async collect(): Promise<SystemStats> {
    try {
      const memoryUsage = process.memoryUsage();
      const cpu = this.calculateCpuUsage();

      this.latestStats = {
        timestamp: Date.now(),
        cpu,
        memory: {
          heapUsed: memoryUsage.heapUsed,
          heapTotal: memoryUsage.heapTotal,
          rss: memoryUsage.rss,
          external: memoryUsage.external
        },
        eventLoopDelay: this.eventLoopLag
      };

      return this.latestStats;
    } catch (error) {
      console.error('Error collecting stats:', error);
      throw error;
    }
  }

  public getLatest(): SystemStats {
    return this.latestStats;
  }
}
