import { ListingRejectedEvent } from '@modules/admin/domain/events/listing-rejected.event';
import type { SendNotificationCommand } from '../commands/send-notification/send-notification.command';
import { ListingRejectedListener } from '../listeners/listing-rejected.listener';

describe('ListingRejectedListener', () => {
  let listener: ListingRejectedListener;
  let mockCommandBus: { execute: ReturnType<typeof vi.fn> };
  let mockPrisma: { listing: { findUnique: ReturnType<typeof vi.fn> } };
  let mockLogger: { log: ReturnType<typeof vi.fn>; warn: ReturnType<typeof vi.fn>; error: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    mockCommandBus = { execute: vi.fn().mockResolvedValue(undefined) };
    mockPrisma = {
      listing: { findUnique: vi.fn() },
    };
    mockLogger = { log: vi.fn(), warn: vi.fn(), error: vi.fn() };

    listener = new ListingRejectedListener(
      mockCommandBus as any,
      mockPrisma as any,
      mockLogger as any,
    );
  });

  it('sends email notification when listing is rejected', async () => {
    mockPrisma.listing.findUnique.mockResolvedValue({
      property: { title: 'Nhà phố Quận 1' },
      seller: { id: 'seller-1', email: 'seller@test.com' },
    });

    const event = new ListingRejectedEvent('listing-1', 'admin-1', 'Hình ảnh không rõ ràng');
    await listener.handle(event);

    const cmd = mockCommandBus.execute.mock.calls[0]![0] as SendNotificationCommand;
    expect(cmd.userId).toBe('seller-1');
    expect(cmd.channel).toBe('EMAIL');
    expect(cmd.templateKey).toBe('listing.rejected');
    expect(cmd.templateData).toEqual({
      listingTitle: 'Nhà phố Quận 1',
      reason: 'Hình ảnh không rõ ràng',
    });
  });

  it('skips notification when listing not found', async () => {
    mockPrisma.listing.findUnique.mockResolvedValue(null);

    const event = new ListingRejectedEvent('listing-1', 'admin-1', 'reason');
    await listener.handle(event);

    expect(mockCommandBus.execute).not.toHaveBeenCalled();
  });
});
