import { describe, it, expect } from 'vitest';
import { ListingEntity } from '../entities/listing.entity';
import { Price } from '../value-objects/price.vo';

describe('ListingEntity', () => {
  const makeDefaultListing = () => {
    const price = Price.create(5_000_000_000n).unwrap();
    return ListingEntity.createNew(
      'listing-1',
      'property-1',
      'seller-1',
      'SALE',
      price,
      100,
      'agent-1',
    );
  };

  it('should create a new listing in DRAFT status', () => {
    const listing = makeDefaultListing();
    expect(listing.status).toBe('DRAFT');
    expect(listing.propertyId).toBe('property-1');
    expect(listing.sellerId).toBe('seller-1');
    expect(listing.transactionType).toBe('SALE');
    expect(listing.pricePerM2).toBe(50_000_000);
    expect(listing.viewCount).toBe(0);
  });

  it('should emit ListingCreatedEvent on creation', () => {
    const listing = makeDefaultListing();
    const events = listing.domainEvents;
    expect(events).toHaveLength(1);
    expect(events[0]!.eventName).toBe('listing.created');
  });

  it('should transition DRAFT -> PENDING_REVIEW', () => {
    const listing = makeDefaultListing();
    listing.submitForReview();
    expect(listing.status).toBe('PENDING_REVIEW');
  });

  it('should transition PENDING_REVIEW -> ACTIVE and emit ListingApprovedEvent', () => {
    const listing = makeDefaultListing();
    listing.clearDomainEvents();
    listing.submitForReview();
    listing.approve();
    expect(listing.status).toBe('ACTIVE');
    expect(listing.publishedAt).toBeTruthy();

    const events = listing.domainEvents;
    expect(events.some((e) => e.eventName === 'listing.approved')).toBe(true);
  });

  it('should reject a PENDING_REVIEW listing', () => {
    const listing = makeDefaultListing();
    listing.submitForReview();
    listing.reject('Ảnh không rõ ràng');
    expect(listing.status).toBe('REJECTED');
    expect(listing.moderationNotes).toBe('Ảnh không rõ ràng');
  });

  it('should transition ACTIVE -> SOLD and emit ListingSoldEvent', () => {
    const listing = makeDefaultListing();
    listing.clearDomainEvents();
    listing.submitForReview();
    listing.approve();
    listing.clearDomainEvents();
    listing.transitionTo('SOLD');
    expect(listing.status).toBe('SOLD');

    const events = listing.domainEvents;
    expect(events.some((e) => e.eventName === 'listing.sold')).toBe(true);
  });

  it('should throw on invalid status transition', () => {
    const listing = makeDefaultListing();
    expect(() => listing.transitionTo('ACTIVE')).toThrow('Không thể chuyển trạng thái');
  });

  it('should not allow transition from SOLD', () => {
    const listing = makeDefaultListing();
    listing.submitForReview();
    listing.approve();
    listing.transitionTo('SOLD');
    expect(() => listing.transitionTo('ACTIVE')).toThrow();
  });

  it('should allow REJECTED -> DRAFT', () => {
    const listing = makeDefaultListing();
    listing.submitForReview();
    listing.reject('Nội dung vi phạm');
    listing.transitionTo('DRAFT');
    expect(listing.status).toBe('DRAFT');
  });

  it('should increment view count', () => {
    const listing = makeDefaultListing();
    listing.incrementViewCount();
    listing.incrementViewCount();
    expect(listing.viewCount).toBe(2);
  });
});
