import { Server as HTTPServer } from 'http';
import { Server as SocketIOServer, Socket } from 'socket.io';

export interface SystemMetrics {
  timestamp: number;
  cpuUsage: number;
  memoryUsage: number;
  diskUsage: number;
  requestsPerSecond: number;
  errorRate: number;
  databaseLatency: number;
  cacheHitRate: number;
}

export interface HealthCheck {
  name: string;
  status: 'healthy' | 'warning' | 'critical';
  message: string;
  lastChecked: number;
  responseTime?: number;
}

class SystemMonitoringManager {
  private io: SocketIOServer;
  private subscribers: Set<string> = new Set();
  private metricsHistory: SystemMetrics[] = [];
  private healthChecks: HealthCheck[] = [];
  private maxHistorySize = 60;

  constructor(httpServer: HTTPServer) {
    this.io = new SocketIOServer(httpServer, {
      cors: {
        origin: process.env.FRONTEND_URL || '*',
        credentials: true,
      },
      transports: ['websocket', 'polling'],
    });

    this.setupEventHandlers();
    this.startMetricsCollection();
  }

  private setupEventHandlers() {
    this.io.on('connection', (socket: Socket) => {
      console.log(`[SystemMonitoring] Client connected: ${socket.id}`);

      socket.on('subscribe', (data: { channel: string }) => {
        if (data.channel === 'system-monitoring') {
          this.subscribers.add(socket.id);
          console.log(`[SystemMonitoring] Client ${socket.id} subscribed`);

          // Send current metrics history
          socket.emit('metrics-history', {
            metrics: this.metricsHistory,
            healthChecks: this.healthChecks,
          });
        }
      });

      socket.on('disconnect', () => {
        this.subscribers.delete(socket.id);
        console.log(`[SystemMonitoring] Client ${socket.id} disconnected`);
      });
    });
  }

  private startMetricsCollection() {
    // Simulate metrics collection every 5 seconds
    setInterval(() => {
      const metrics = this.generateMetrics();
      this.metricsHistory.push(metrics);

      if (this.metricsHistory.length > this.maxHistorySize) {
        this.metricsHistory.shift();
      }

      // Broadcast to all subscribers
      this.io.emit('metrics', { data: metrics });

      // Update health checks every 30 seconds
      if (Math.random() > 0.8) {
        this.healthChecks = this.generateHealthChecks();
        this.io.emit('health-check', { data: this.healthChecks });
      }
    }, 5000);
  }

  private generateMetrics(): SystemMetrics {
    return {
      timestamp: Date.now(),
      cpuUsage: Math.random() * 100,
      memoryUsage: Math.random() * 100,
      diskUsage: Math.random() * 100,
      requestsPerSecond: Math.floor(Math.random() * 1000),
      errorRate: Math.random() * 5,
      databaseLatency: Math.random() * 500,
      cacheHitRate: 50 + Math.random() * 50,
    };
  }

  private generateHealthChecks(): HealthCheck[] {
    return [
      {
        name: 'Database',
        status: Math.random() > 0.1 ? 'healthy' : 'warning',
        message: 'Database connection pool healthy',
        lastChecked: Date.now(),
        responseTime: Math.random() * 100,
      },
      {
        name: 'Redis Cache',
        status: Math.random() > 0.05 ? 'healthy' : 'critical',
        message: 'Cache server operational',
        lastChecked: Date.now(),
        responseTime: Math.random() * 50,
      },
      {
        name: 'API Gateway',
        status: Math.random() > 0.02 ? 'healthy' : 'warning',
        message: 'API gateway responding normally',
        lastChecked: Date.now(),
        responseTime: Math.random() * 200,
      },
      {
        name: 'Payment Processor',
        status: Math.random() > 0.05 ? 'healthy' : 'warning',
        message: 'Payment processor connected',
        lastChecked: Date.now(),
        responseTime: Math.random() * 300,
      },
      {
        name: 'Email Service',
        status: Math.random() > 0.1 ? 'healthy' : 'warning',
        message: 'Email service available',
        lastChecked: Date.now(),
        responseTime: Math.random() * 150,
      },
    ];
  }

  public getMetricsHistory(): SystemMetrics[] {
    return this.metricsHistory;
  }

  public getHealthChecks(): HealthCheck[] {
    return this.healthChecks;
  }

  public getConnectedCount(): number {
    return this.subscribers.size;
  }
}

let systemMonitoringManager: SystemMonitoringManager;

export function initializeSystemMonitoring(httpServer: HTTPServer): SystemMonitoringManager {
  if (!systemMonitoringManager) {
    systemMonitoringManager = new SystemMonitoringManager(httpServer);
  }
  return systemMonitoringManager;
}

export function getSystemMonitoringManager(): SystemMonitoringManager {
  if (!systemMonitoringManager) {
    throw new Error('SystemMonitoringManager not initialized');
  }
  return systemMonitoringManager;
}
