import { describe, it, expect } from 'vitest';
import { ListingApprovedEvent } from '../events/listing-approved.event';
import { ListingCreatedEvent } from '../events/listing-created.event';
import { ListingPriceChangedEvent } from '../events/listing-price-changed.event';
import { ListingSoldEvent } from '../events/listing-sold.event';
import { ListingStatusChangedEvent } from '../events/listing-status-changed.event';

describe('Listings Domain Events', () => {
  describe('ListingCreatedEvent', () => {
    it('creates event with correct properties', () => {
      const event = new ListingCreatedEvent('listing-1', 'prop-1', 'seller-1', 'SALE');

      expect(event.eventName).toBe('listing.created');
      expect(event.aggregateId).toBe('listing-1');
      expect(event.propertyId).toBe('prop-1');
      expect(event.sellerId).toBe('seller-1');
      expect(event.transactionType).toBe('SALE');
      expect(event.occurredAt).toBeInstanceOf(Date);
    });

    it('creates event for RENT transaction', () => {
      const event = new ListingCreatedEvent('listing-2', 'prop-2', 'seller-2', 'RENT');
      expect(event.transactionType).toBe('RENT');
    });
  });

  describe('ListingApprovedEvent', () => {
    it('creates event with correct properties', () => {
      const event = new ListingApprovedEvent('listing-1', 'prop-1');

      expect(event.eventName).toBe('listing.approved');
      expect(event.aggregateId).toBe('listing-1');
      expect(event.propertyId).toBe('prop-1');
      expect(event.occurredAt).toBeInstanceOf(Date);
    });
  });

  describe('ListingSoldEvent', () => {
    it('creates event with SOLD status', () => {
      const event = new ListingSoldEvent('listing-1', 'prop-1', 'SOLD');

      expect(event.eventName).toBe('listing.sold');
      expect(event.aggregateId).toBe('listing-1');
      expect(event.propertyId).toBe('prop-1');
      expect(event.finalStatus).toBe('SOLD');
      expect(event.occurredAt).toBeInstanceOf(Date);
    });

    it('creates event with RENTED status', () => {
      const event = new ListingSoldEvent('listing-2', 'prop-2', 'RENTED');
      expect(event.finalStatus).toBe('RENTED');
    });
  });

  describe('ListingPriceChangedEvent', () => {
    it('creates event with correct properties', () => {
      const event = new ListingPriceChangedEvent('listing-1', 5_000_000_000n, 6_000_000_000n, 'manual_update');

      expect(event.eventName).toBe('listing.price_changed');
      expect(event.aggregateId).toBe('listing-1');
      expect(event.oldPrice).toBe(5_000_000_000n);
      expect(event.newPrice).toBe(6_000_000_000n);
      expect(event.source).toBe('manual_update');
      expect(event.occurredAt).toBeInstanceOf(Date);
    });

    it('defaults source to manual_update', () => {
      const event = new ListingPriceChangedEvent('listing-2', 1_000_000n, 2_000_000n);
      expect(event.source).toBe('manual_update');
    });

    it('accepts admin_override source', () => {
      const event = new ListingPriceChangedEvent('listing-3', 1n, 2n, 'admin_override');
      expect(event.source).toBe('admin_override');
    });

    it('accepts market_adjustment source', () => {
      const event = new ListingPriceChangedEvent('listing-4', 1n, 2n, 'market_adjustment');
      expect(event.source).toBe('market_adjustment');
    });
  });

  describe('ListingStatusChangedEvent', () => {
    it('creates event with correct properties', () => {
      const event = new ListingStatusChangedEvent('listing-1', 'prop-1', 'DRAFT', 'PENDING_REVIEW');

      expect(event.eventName).toBe('listing.status_changed');
      expect(event.aggregateId).toBe('listing-1');
      expect(event.propertyId).toBe('prop-1');
      expect(event.previousStatus).toBe('DRAFT');
      expect(event.newStatus).toBe('PENDING_REVIEW');
      expect(event.occurredAt).toBeInstanceOf(Date);
    });

    it('creates event for rejection transition', () => {
      const event = new ListingStatusChangedEvent('listing-2', 'prop-2', 'PENDING_REVIEW', 'REJECTED');
      expect(event.previousStatus).toBe('PENDING_REVIEW');
      expect(event.newStatus).toBe('REJECTED');
    });

    it('creates event for expiration transition', () => {
      const event = new ListingStatusChangedEvent('listing-3', 'prop-3', 'ACTIVE', 'EXPIRED');
      expect(event.previousStatus).toBe('ACTIVE');
      expect(event.newStatus).toBe('EXPIRED');
    });
  });
});
