import { describe, it, expect, beforeEach } from 'vitest';
import { websocketMonitoringService } from './websocketMonitoring.ts';

describe('WebSocket Monitoring Service', () => {
  beforeEach(() => {
    // Reset service state before each test
    websocketMonitoringService.cleanup();
  });

  describe('recordMetrics', () => {
    it('should record connection metrics', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 150,
        activityFeedConnections: 80,
        revenueForecastConnections: 70,
        messagesSent: 1000,
        messagesReceived: 950,
        averageLatency: 45,
        errorCount: 2,
      });

      const metrics = websocketMonitoringService.getMetrics(24);
      expect(metrics).toHaveLength(1);
      expect(metrics[0].activeConnections).toBe(150);
      expect(metrics[0].averageLatency).toBe(45);
    });

    it('should calculate average connections correctly', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 40,
        errorCount: 1,
      });

      websocketMonitoringService.recordMetrics({
        activeConnections: 200,
        activityFeedConnections: 100,
        revenueForecastConnections: 100,
        messagesSent: 1000,
        messagesReceived: 950,
        averageLatency: 50,
        errorCount: 2,
      });

      const avgConnections = websocketMonitoringService.getAverageConnections(24);
      expect(avgConnections).toBe(150);
    });

    it('should track peak connections', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 40,
        errorCount: 1,
      });

      websocketMonitoringService.recordMetrics({
        activeConnections: 300,
        activityFeedConnections: 150,
        revenueForecastConnections: 150,
        messagesSent: 1500,
        messagesReceived: 1400,
        averageLatency: 60,
        errorCount: 3,
      });

      const peakConnections = websocketMonitoringService.getPeakConnections(24);
      expect(peakConnections).toBe(300);
    });
  });

  describe('recordDeliveryAlert', () => {
    it('should record email delivery alert', () => {
      websocketMonitoringService.recordDeliveryAlert({
        type: 'email_failure',
        severity: 'high',
        message: 'Failed to send campaign email',
        details: { campaignId: 123, recipientCount: 500 },
      });

      const failures = websocketMonitoringService.getDeliveryFailureRate(24);
      expect(failures.emailFailures).toBe(1);
      expect(failures.totalFailures).toBe(1);
    });

    it('should record SMS delivery alert', () => {
      websocketMonitoringService.recordDeliveryAlert({
        type: 'sms_failure',
        severity: 'medium',
        message: 'SMS delivery failed',
        details: { phoneNumber: '+1234567890' },
      });

      const failures = websocketMonitoringService.getDeliveryFailureRate(24);
      expect(failures.smsFailures).toBe(1);
    });

    it('should track multiple delivery failures', () => {
      for (let i = 0; i < 5; i++) {
        websocketMonitoringService.recordDeliveryAlert({
          type: 'email_failure',
          severity: 'high',
          message: `Email failure ${i}`,
        });
      }

      const failures = websocketMonitoringService.getDeliveryFailureRate(24);
      expect(failures.emailFailures).toBe(5);
      expect(failures.totalFailures).toBe(5);
    });
  });

  describe('recordAccuracyAlert', () => {
    it('should record forecast accuracy alert', () => {
      websocketMonitoringService.recordAccuracyAlert({
        modelType: 'ml',
        accuracy: 82,
        threshold: 85,
        drift: -3,
        recommendation: 'Retrain model with recent data',
      });

      const summary = websocketMonitoringService.getForecastAccuracySummary(24);
      expect(summary).toHaveLength(1);
      expect(summary[0].modelType).toBe('ml');
      expect(summary[0].currentAccuracy).toBe(82);
    });

    it('should detect accuracy trends', () => {
      // Record improving trend
      for (let i = 0; i < 5; i++) {
        websocketMonitoringService.recordAccuracyAlert({
          modelType: 'ml',
          accuracy: 70 + i * 2,
          threshold: 85,
          drift: 0,
          recommendation: 'Monitor performance',
        });
      }

      const summary = websocketMonitoringService.getForecastAccuracySummary(24);
      expect(summary[0].trend).toBe('improving');
    });
  });

  describe('getHealthStatus', () => {
    it('should report healthy status', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 50,
        errorCount: 0,
      });

      const health = websocketMonitoringService.getHealthStatus();
      expect(health.status).toBe('healthy');
      expect(health.issues).toHaveLength(0);
    });

    it('should detect high latency issues', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 1500, // High latency
        errorCount: 0,
      });

      const health = websocketMonitoringService.getHealthStatus();
      expect(health.status).toBe('degraded');
      expect(health.issues.some((i) => i.includes('latency'))).toBe(true);
    });

    it('should detect high error rates', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 50,
        errorCount: 15, // High error count
      });

      const health = websocketMonitoringService.getHealthStatus();
      expect(health.status).toBe('degraded');
      expect(health.issues.some((i) => i.includes('error'))).toBe(true);
    });

    it('should detect delivery failures', () => {
      for (let i = 0; i < 10; i++) {
        websocketMonitoringService.recordDeliveryAlert({
          type: 'email_failure',
          severity: 'high',
          message: `Email failure ${i}`,
        });
      }

      const health = websocketMonitoringService.getHealthStatus();
      expect(health.status).toBe('degraded');
      expect(health.issues.some((i) => i.includes('Email'))).toBe(true);
    });

    it('should detect low forecast accuracy', () => {
      websocketMonitoringService.recordAccuracyAlert({
        modelType: 'ml',
        accuracy: 65, // Below threshold
        threshold: 85,
        drift: -20,
        recommendation: 'Retrain model',
      });

      const health = websocketMonitoringService.getHealthStatus();
      expect(health.status).toBe('degraded');
      expect(health.issues.some((i) => i.includes('accuracy'))).toBe(true);
    });

    it('should report critical status when multiple issues exist', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 1500,
        errorCount: 20,
      });

      for (let i = 0; i < 25; i++) {
        websocketMonitoringService.recordDeliveryAlert({
          type: 'email_failure',
          severity: 'high',
          message: `Email failure ${i}`,
        });
      }

      const health = websocketMonitoringService.getHealthStatus();
      expect(health.status).toBe('critical');
      expect(health.issues.length).toBeGreaterThan(0);
      expect(health.recommendations.length).toBeGreaterThan(0);
    });
  });

  describe('getMetrics', () => {
    it('should filter metrics by time range', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 50,
        errorCount: 0,
      });

      const metricsLast24h = websocketMonitoringService.getMetrics(24);
      expect(metricsLast24h).toHaveLength(1);

      const metricsLast1h = websocketMonitoringService.getMetrics(1);
      expect(metricsLast1h).toHaveLength(1);
    });
  });

  describe('cleanup', () => {
    it('should remove old data', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 50,
        errorCount: 0,
      });








  });
});

  describe('cleanup', () => {
    it('should preserve recent data during cleanup', () => {
      websocketMonitoringService.recordMetrics({
        activeConnections: 100,
        activityFeedConnections: 50,
        revenueForecastConnections: 50,
        messagesSent: 500,
        messagesReceived: 480,
        averageLatency: 50,
        errorCount: 0,
      });

      const metricsBeforeCleanup = websocketMonitoringService.getMetrics(24);
      const countBefore = metricsBeforeCleanup.length;

      websocketMonitoringService.cleanup();

      const metricsAfterCleanup = websocketMonitoringService.getMetrics(24);
      expect(metricsAfterCleanup.length).toBeLessThanOrEqual(countBefore);
    });
  });
});
