import { describe, it, expect, beforeEach, vi } from 'vitest';
import { alertTriggerService } from './alertTriggerService.ts';

describe('alertTriggerService', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('evaluateThreshold', () => {
    it('should evaluate greater than operator', () => {
      const threshold = { metric: 'latency', operator: 'gt' as const, value: 500, severity: 'critical' as const };
      
      // Access private method through type assertion
      const service = alertTriggerService as any;
      expect(service.evaluateThreshold(600, threshold)).toBe(true);
      expect(service.evaluateThreshold(400, threshold)).toBe(false);
    });

    it('should evaluate less than operator', () => {
      const threshold = { metric: 'success_rate', operator: 'lt' as const, value: 0.9, severity: 'warning' as const };
      
      const service = alertTriggerService as any;
      expect(service.evaluateThreshold(0.8, threshold)).toBe(true);
      expect(service.evaluateThreshold(0.95, threshold)).toBe(false);
    });

    it('should evaluate greater than or equal operator', () => {
      const threshold = { metric: 'connections', operator: 'gte' as const, value: 100, severity: 'info' as const };
      
      const service = alertTriggerService as any;
      expect(service.evaluateThreshold(100, threshold)).toBe(true);
      expect(service.evaluateThreshold(101, threshold)).toBe(true);
      expect(service.evaluateThreshold(99, threshold)).toBe(false);
    });

    it('should evaluate less than or equal operator', () => {
      const threshold = { metric: 'accuracy', operator: 'lte' as const, value: 0.85, severity: 'warning' as const };
      
      const service = alertTriggerService as any;
      expect(service.evaluateThreshold(0.85, threshold)).toBe(true);
      expect(service.evaluateThreshold(0.84, threshold)).toBe(true);
      expect(service.evaluateThreshold(0.86, threshold)).toBe(false);
    });

    it('should evaluate equality operator', () => {
      const threshold = { metric: 'status', operator: 'eq' as const, value: 0, severity: 'critical' as const };
      
      const service = alertTriggerService as any;
      expect(service.evaluateThreshold(0, threshold)).toBe(true);
      expect(service.evaluateThreshold(1, threshold)).toBe(false);
    });
  });

  describe('getThresholds', () => {
    it('should return all configured thresholds', () => {
      const thresholds = alertTriggerService.getThresholds();

      expect(thresholds).toHaveProperty('latency_critical');
      expect(thresholds).toHaveProperty('latency_warning');
      expect(thresholds).toHaveProperty('delivery_failure');
      expect(thresholds).toHaveProperty('forecast_accuracy_degrading');
      expect(thresholds).toHaveProperty('connection_drop');
    });

    it('should have valid threshold structure', () => {
      const thresholds = alertTriggerService.getThresholds();

      Object.values(thresholds).forEach((threshold) => {
        expect(threshold).toHaveProperty('metric');
        expect(threshold).toHaveProperty('operator');
        expect(threshold).toHaveProperty('value');
        expect(threshold).toHaveProperty('severity');
        expect(['gt', 'lt', 'gte', 'lte', 'eq']).toContain(threshold.operator);
        expect(['critical', 'warning', 'info']).toContain(threshold.severity);
      });
    });
  });

  describe('updateThreshold', () => {
    it('should update existing threshold', () => {
      const newThreshold = {
        metric: 'websocket_latency',
        operator: 'gt' as const,
        value: 1000,
        severity: 'critical' as const,
      };

      alertTriggerService.updateThreshold('latency_critical', newThreshold);
      const thresholds = alertTriggerService.getThresholds();

      expect(thresholds.latency_critical.value).toBe(1000);
    });

    it('should add new threshold', () => {
      const newThreshold = {
        metric: 'custom_metric',
        operator: 'gt' as const,
        value: 50,
        severity: 'warning' as const,
      };

      alertTriggerService.updateThreshold('custom_alert', newThreshold);
      const thresholds = alertTriggerService.getThresholds();

      expect(thresholds).toHaveProperty('custom_alert');
      expect(thresholds.custom_alert.value).toBe(50);
    });
  });

  describe('getActiveAlerts', () => {
    it('should return empty array initially', () => {
      const alerts = alertTriggerService.getActiveAlerts();
      expect(Array.isArray(alerts)).toBe(true);
    });

    it('should return active alerts', () => {
      const alerts = alertTriggerService.getActiveAlerts();
      expect(Array.isArray(alerts)).toBe(true);
    });
  });

  describe('startMonitoring', () => {
    it('should return a timer', () => {
      const timer = alertTriggerService.startMonitoring(1000);
      expect(timer).toBeDefined();
      clearInterval(timer);
    });

    it('should use default interval if not specified', () => {
      const timer = alertTriggerService.startMonitoring();
      expect(timer).toBeDefined();
      clearInterval(timer);
    });
  });

  describe('checkMetrics', () => {
    it('should return array of alerts', async () => {
      const alerts = await alertTriggerService.checkMetrics();
      expect(Array.isArray(alerts)).toBe(true);
    });

    it('should handle errors gracefully', async () => {
      const alerts = await alertTriggerService.checkMetrics();
      expect(Array.isArray(alerts)).toBe(true);
    });
  });

  describe('resolveAlert', () => {
    it('should return boolean', async () => {
      const result = await alertTriggerService.resolveAlert('non-existent-alert');
      expect(typeof result).toBe('boolean');
    });
  });

  describe('acknowledgeAlert', () => {
    it('should return boolean', async () => {
      const result = await alertTriggerService.acknowledgeAlert('non-existent-alert');
      expect(typeof result).toBe('boolean');
    });
  });
});
