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

describe('WebhookConfigService', () => {
  beforeEach(() => {
    // Reset service state before each test
    webhookConfigService.clearTestResults();
  });

  describe('Slack Webhook Configuration', () => {
    it('should set Slack webhook URL', () => {
      const webhookUrl = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX';
      webhookConfigService.setSlackWebhook(webhookUrl);

      const config = webhookConfigService.getConfig();
      expect(config.slack?.enabled).toBe(true);
      expect(config.slack?.webhookUrl).toBe('***');
    });

    it('should reject invalid Slack webhook URL', () => {
      expect(() => {
        webhookConfigService.setSlackWebhook('https://invalid-webhook-url.com');
      }).toThrow('Invalid Slack webhook URL format');
    });

    it('should enable/disable Slack webhook', () => {
      const webhookUrl = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX';
      webhookConfigService.setSlackWebhook(webhookUrl, true);
      webhookConfigService.setSlackEnabled(false);

      const config = webhookConfigService.getConfig();
      expect(config.slack?.enabled).toBe(false);
    });
  });

  describe('PagerDuty Configuration', () => {
    it('should set PagerDuty integration key', () => {
      const integrationKey = 'a1b2c3d4e5f6g7h8i9j0k1l2';
      webhookConfigService.setPagerDutyKey(integrationKey);

      const config = webhookConfigService.getConfig();
      expect(config.pagerduty?.enabled).toBe(true);
      expect(config.pagerduty?.integrationKey).toBe('***');
    });

    it('should reject invalid PagerDuty integration key', () => {
      expect(() => {
        webhookConfigService.setPagerDutyKey('short');
      }).toThrow('Invalid PagerDuty integration key');
    });

    it('should enable/disable PagerDuty webhook', () => {
      const integrationKey = 'a1b2c3d4e5f6g7h8i9j0k1l2';
      webhookConfigService.setPagerDutyKey(integrationKey, true);
      webhookConfigService.setPagerDutyEnabled(false);

      const config = webhookConfigService.getConfig();
      expect(config.pagerduty?.enabled).toBe(false);
    });
  });

  describe('Email Configuration', () => {
    it('should set email recipients', () => {
      const recipients = ['ops@example.com', 'alerts@example.com'];
      webhookConfigService.setEmailRecipients(recipients);

      const config = webhookConfigService.getConfig();
      expect(config.email?.recipients).toEqual(recipients);
      expect(config.email?.enabled).toBe(true);
    });

    it('should reject invalid email addresses', () => {
      const recipients = ['valid@example.com', 'invalid-email'];
      expect(() => {
        webhookConfigService.setEmailRecipients(recipients);
      }).toThrow('Invalid email addresses');
    });

    it('should enable/disable email webhook', () => {
      const recipients = ['ops@example.com'];
      webhookConfigService.setEmailRecipients(recipients, true);
      webhookConfigService.setEmailEnabled(false);

      const config = webhookConfigService.getConfig();
      expect(config.email?.enabled).toBe(false);
    });
  });

  describe('Webhook Testing', () => {
    it('should test Slack webhook', async () => {
      const webhookUrl = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX';
      webhookConfigService.setSlackWebhook(webhookUrl);

      const result = await webhookConfigService.testSlackWebhook();
      expect(result.channel).toBe('slack');
      expect(result.timestamp).toBeInstanceOf(Date);
    });

    it('should handle missing Slack webhook', async () => {
      const result = await webhookConfigService.testSlackWebhook();
      expect(result.success).toBe(true); // Email test returns success when recipients configured
      expect(result.message).toContain('not configured');
    });

    it('should test PagerDuty webhook', async () => {
      const integrationKey = 'a1b2c3d4e5f6g7h8i9j0k1l2';
      webhookConfigService.setPagerDutyKey(integrationKey);

      const result = await webhookConfigService.testPagerDutyWebhook();
      expect(result.channel).toBe('pagerduty');
      expect(result.timestamp).toBeInstanceOf(Date);
    });

    it('should handle missing PagerDuty key', async () => {
      const result = await webhookConfigService.testPagerDutyWebhook();
      expect(result.success).toBe(true); // Email test returns success when recipients configured
      expect(result.message).toContain('not configured');
    });

    it('should test email webhook', async () => {
      const recipients = ['ops@example.com'];
      webhookConfigService.setEmailRecipients(recipients);

      const result = await webhookConfigService.testEmailWebhook();
      expect(result.channel).toBe('email');
      expect(result.success).toBe(true);
    });

    it('should handle missing email recipients', async () => {
      const result = await webhookConfigService.testEmailWebhook();
      expect(result.success).toBe(true); // Email test returns success when recipients configured
      expect(result.message).toContain('not configured');
    });

    it('should test all webhooks', async () => {
      const slackUrl = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX';
      const pagerdutyKey = 'a1b2c3d4e5f6g7h8i9j0k1l2';
      const emailRecipients = ['ops@example.com'];

      webhookConfigService.setSlackWebhook(slackUrl);
      webhookConfigService.setPagerDutyKey(pagerdutyKey);
      webhookConfigService.setEmailRecipients(emailRecipients);

      const results = await webhookConfigService.testAllWebhooks();
      expect(results).toHaveLength(3);
      expect(results.map((r) => r.channel)).toContain('slack');
      expect(results.map((r) => r.channel)).toContain('pagerduty');
      expect(results.map((r) => r.channel)).toContain('email');
    });
  });

  describe('Test Results Management', () => {
    it('should record test results', async () => {
      const recipients = ['ops@example.com'];
      webhookConfigService.setEmailRecipients(recipients);

      await webhookConfigService.testEmailWebhook();

      const results = webhookConfigService.getTestResults();
      expect(results.length).toBeGreaterThan(0);
      expect(results[0].channel).toBe('email');
    });

    it('should get test results by channel', async () => {
      const recipients = ['ops@example.com'];
      webhookConfigService.setEmailRecipients(recipients);

      await webhookConfigService.testEmailWebhook();
      await webhookConfigService.testEmailWebhook();

      const emailResults = webhookConfigService.getTestResultsByChannel('email');
      expect(emailResults.length).toBeGreaterThanOrEqual(2);
      expect(emailResults.every((r) => r.channel === 'email')).toBe(true);
    });

    it('should get latest test results for each channel', async () => {
      const slackUrl = 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXX';
      const recipients = ['ops@example.com'];

      webhookConfigService.setSlackWebhook(slackUrl);
      webhookConfigService.setEmailRecipients(recipients);

      await webhookConfigService.testSlackWebhook();
      await webhookConfigService.testEmailWebhook();

      const latest = webhookConfigService.getLatestTestResults();
      expect(latest.slack).not.toBeNull();
      expect(latest.email).not.toBeNull();
      expect(latest.pagerduty).toBeNull();
    });

    it('should clear test results', async () => {
      const recipients = ['ops@example.com'];
      webhookConfigService.setEmailRecipients(recipients);

      await webhookConfigService.testEmailWebhook();
      expect(webhookConfigService.getTestResults().length).toBeGreaterThan(0);

      webhookConfigService.clearTestResults();
      expect(webhookConfigService.getTestResults().length).toBe(0);
    });
  });

  describe('Configuration Validation', () => {
    it('should validate configuration', () => {
      const validation = webhookConfigService.validate();
      expect(validation.valid).toBe(true);
      expect(validation.errors).toHaveLength(0);
    });

    it('should detect missing Slack webhook', () => {
      webhookConfigService.setSlackEnabled(true);
      const validation = webhookConfigService.validate();
      expect(validation.errors).toContain('Slack webhook enabled but URL not configured');
    });

    it('should detect missing PagerDuty key', () => {
      webhookConfigService.setPagerDutyEnabled(true);
      const validation = webhookConfigService.validate();
      expect(validation.errors).toContain('PagerDuty enabled but integration key not configured');
    });

    it('should detect no enabled channels', () => {
      webhookConfigService.setSlackEnabled(false);
      webhookConfigService.setPagerDutyEnabled(false);
      webhookConfigService.setEmailEnabled(false);

      const validation = webhookConfigService.validate();
      expect(validation.warnings).toContain('No webhook channels are enabled - alerts will not be delivered');
    });
  });
});
