import { type CommandBus } from '@nestjs/cqrs';
import { MeterUsageCommand } from '../../application/commands/meter-usage/meter-usage.command';
import { ListingCreatedUsageHandler } from '../event-handlers/listing-created-usage.handler';

describe('ListingCreatedUsageHandler', () => {
  let handler: ListingCreatedUsageHandler;
  let mockCommandBus: { execute: ReturnType<typeof vi.fn> };

  beforeEach(() => {
    mockCommandBus = { execute: vi.fn() };
    const mockLogger = { log: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(), verbose: vi.fn() };
    handler = new ListingCreatedUsageHandler(mockCommandBus as unknown as CommandBus, mockLogger as any);
  });

  it('meters listings_created usage for the seller', async () => {
    mockCommandBus.execute.mockResolvedValue({
      usageRecordId: 'usage-1',
      metric: 'listings_created',
      count: 1,
    });

    await handler.handle({
      eventName: 'listing.created',
      occurredAt: new Date(),
      aggregateId: 'listing-1',
      propertyId: 'prop-1',
      sellerId: 'user-1',
      transactionType: 'SALE',
    } as any);

    expect(mockCommandBus.execute).toHaveBeenCalledWith(
      new MeterUsageCommand('user-1', 'listings_created', 1),
    );
  });

  it('does not throw when metering fails (best-effort)', async () => {
    mockCommandBus.execute.mockRejectedValue(new Error('Subscription not found'));

    await expect(
      handler.handle({
        eventName: 'listing.created',
        occurredAt: new Date(),
        aggregateId: 'listing-1',
        propertyId: 'prop-1',
        sellerId: 'user-99',
        transactionType: 'SALE',
      } as any),
    ).resolves.not.toThrow();
  });

  it('calls MeterUsageCommand with count of 1', async () => {
    mockCommandBus.execute.mockResolvedValue({});

    await handler.handle({
      eventName: 'listing.created',
      occurredAt: new Date(),
      aggregateId: 'listing-2',
      propertyId: 'prop-2',
      sellerId: 'user-2',
      transactionType: 'RENT',
    } as any);

    const command = mockCommandBus.execute.mock.calls[0]![0] as MeterUsageCommand;
    expect(command.userId).toBe('user-2');
    expect(command.metric).toBe('listings_created');
    expect(command.count).toBe(1);
  });
});
