import { UserRegisteredEvent } from '@modules/auth/domain/events/user-registered.event';
import { SendNotificationCommand } from '../commands/send-notification/send-notification.command';
import { UserRegisteredListener } from '../listeners/user-registered.listener';

describe('UserRegisteredListener', () => {
  let listener: UserRegisteredListener;
  let mockCommandBus: { execute: ReturnType<typeof vi.fn> };
  let mockPrisma: { user: { 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 = {
      user: {
        findUnique: vi.fn(),
      },
    };
    mockLogger = { log: vi.fn(), warn: vi.fn(), error: vi.fn() };

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

  it('sends welcome email when user has email', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({
      email: 'user@test.com',
      phone: '0901234567',
    });

    const event = new UserRegisteredEvent('user-1', '0901234567', 'BUYER');
    await listener.handle(event);

    expect(mockCommandBus.execute).toHaveBeenCalledWith(
      expect.any(SendNotificationCommand),
    );

    const cmd = mockCommandBus.execute.mock.calls[0]![0] as SendNotificationCommand;
    expect(cmd.userId).toBe('user-1');
    expect(cmd.channel).toBe('EMAIL');
    expect(cmd.templateKey).toBe('user.registered');
    expect(cmd.templateData).toEqual({ phone: '0901234567', role: 'BUYER' });
    expect(cmd.recipientAddress).toBe('user@test.com');
  });

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

    const event = new UserRegisteredEvent('user-1', '0901234567', 'BUYER');
    await listener.handle(event);

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

  it('skips notification when user has no email', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({
      email: null,
      phone: '0901234567',
    });

    const event = new UserRegisteredEvent('user-1', '0901234567', 'SELLER');
    await listener.handle(event);

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