/**
 * Webhook Entity Tests
 */

import { Webhook, WebhookEvent, WebhookStatus } from './webhook.entity';

describe('Webhook Entity', () => {
  describe('create', () => {
    it('should create a new webhook with default values', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      expect(webhook.id).toBe('webhook-123');
      expect(webhook.status).toBe(WebhookStatus.ACTIVE);
      expect(webhook.retryCount).toBe(0);
      expect(webhook.failureCount).toBe(0);
      expect(webhook.isActive()).toBe(true);
    });

    it('should set provided optional fields', () => {
      const headers = { 'X-Custom': 'value' };
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
        description: 'Test webhook',
        headers,
      });

      expect(webhook.description).toBe('Test webhook');
      expect(webhook.headers).toEqual(headers);
    });
  });

  describe('isActive', () => {
    it('should return true for active webhooks', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      expect(webhook.isActive()).toBe(true);
    });

    it('should return false for inactive webhooks', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      const deactivated = webhook.deactivate();
      expect(deactivated.isActive()).toBe(false);
    });
  });

  describe('subscribesToEvent', () => {
    it('should return true if webhook subscribes to event', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED, WebhookEvent.BOOKING_UPDATED],
        secret: 'secret-key',
      });

      expect(webhook.subscribesToEvent(WebhookEvent.BOOKING_CREATED)).toBe(true);
      expect(webhook.subscribesToEvent(WebhookEvent.BOOKING_UPDATED)).toBe(true);
    });

    it('should return false if webhook does not subscribe to event', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      expect(webhook.subscribesToEvent(WebhookEvent.BOOKING_CANCELLED)).toBe(false);
    });
  });

  describe('activate', () => {
    it('should change status to active', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      const deactivated = webhook.deactivate();
      const activated = deactivated.activate();

      expect(activated.status).toBe(WebhookStatus.ACTIVE);
      expect(activated.isActive()).toBe(true);
    });
  });

  describe('deactivate', () => {
    it('should change status to inactive', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      const deactivated = webhook.deactivate();

      expect(deactivated.status).toBe(WebhookStatus.INACTIVE);
      expect(deactivated.isActive()).toBe(false);
    });
  });

  describe('markAsFailed', () => {
    it('should change status to failed and increment failure count', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      const failed = webhook.markAsFailed();

      expect(failed.status).toBe(WebhookStatus.FAILED);
      expect(failed.failureCount).toBe(1);
    });

    it('should increment failure count on multiple failures', () => {
      let webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      webhook = webhook.markAsFailed();
      webhook = webhook.markAsFailed();
      webhook = webhook.markAsFailed();

      expect(webhook.failureCount).toBe(3);
    });
  });

  describe('recordTrigger', () => {
    it('should update lastTriggeredAt and increment retry count', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      const triggered = webhook.recordTrigger();

      expect(triggered.lastTriggeredAt).toBeDefined();
      expect(triggered.retryCount).toBe(1);
      expect(triggered.failureCount).toBe(0); // Reset on success
    });

    it('should reset failure count on successful trigger', () => {
      let webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      webhook = webhook.markAsFailed();
      webhook = webhook.markAsFailed();
      expect(webhook.failureCount).toBe(2);

      const triggered = webhook.recordTrigger();
      expect(triggered.failureCount).toBe(0);
    });
  });

  describe('update', () => {
    it('should update webhook properties', () => {
      const webhook = Webhook.create({
        id: 'webhook-123',
        organizationId: 'org-123',
        url: 'https://example.com/webhook',
        events: [WebhookEvent.BOOKING_CREATED],
        secret: 'secret-key',
      });

      const updated = webhook.update({
        url: 'https://newurl.com/webhook',
        description: 'Updated webhook',
        events: [WebhookEvent.BOOKING_CREATED, WebhookEvent.BOOKING_UPDATED],
      });

      expect(updated.url).toBe('https://newurl.com/webhook');
      expect(updated.description).toBe('Updated webhook');
      expect(updated.events).toHaveLength(2);
    });
  });
});
