import type { CommandBus } from '@nestjs/cqrs';
import { RecalculateQualityScoreCommand } from '../commands/recalculate-quality-score/recalculate-quality-score.command';
import { ReviewEventsListener } from '../listeners/review-events.listener';

describe('ReviewEventsListener', () => {
  let listener: ReviewEventsListener;
  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() };
    listener = new ReviewEventsListener(mockCommandBus as unknown as CommandBus, mockLogger as any);
  });

  describe('onReviewCreated', () => {
    it('dispatches recalculate command when targetType is AGENT', async () => {
      mockCommandBus.execute.mockResolvedValue(undefined);

      await listener.onReviewCreated({
        targetType: 'AGENT',
        targetId: 'agent-1',
      });

      expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);
      expect(mockCommandBus.execute).toHaveBeenCalledWith(
        expect.any(RecalculateQualityScoreCommand),
      );

      const command = mockCommandBus.execute.mock.calls[0][0] as RecalculateQualityScoreCommand;
      expect(command.agentId).toBe('agent-1');
    });

    it('ignores events when targetType is not AGENT', async () => {
      await listener.onReviewCreated({
        targetType: 'LISTING',
        targetId: 'listing-1',
      });

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

    it('ignores events when targetType is USER', async () => {
      await listener.onReviewCreated({
        targetType: 'USER',
        targetId: 'user-1',
      });

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

  describe('onReviewDeleted', () => {
    it('dispatches recalculate command when targetType is AGENT', async () => {
      mockCommandBus.execute.mockResolvedValue(undefined);

      await listener.onReviewDeleted({
        targetType: 'AGENT',
        targetId: 'agent-2',
      });

      expect(mockCommandBus.execute).toHaveBeenCalledTimes(1);

      const command = mockCommandBus.execute.mock.calls[0][0] as RecalculateQualityScoreCommand;
      expect(command.agentId).toBe('agent-2');
    });

    it('ignores events when targetType is not AGENT', async () => {
      await listener.onReviewDeleted({
        targetType: 'PROPERTY',
        targetId: 'prop-1',
      });

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