import { UserBannedListener } from '../listeners/user-banned.listener';

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

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

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

  it('deactivates all user listings when banned', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({ id: 'user-1', email: 'user@example.com' });

    await listener.handle({
      aggregateId: 'user-1',
      adminId: 'admin-1',
      reason: 'Vi phạm chính sách',
      eventName: 'user.banned',
      occurredAt: new Date(),
    });

    expect(mockPrisma.listing.updateMany).toHaveBeenCalledWith({
      where: {
        sellerId: 'user-1',
        status: { in: ['ACTIVE', 'PENDING_REVIEW', 'DRAFT'] },
      },
      data: { status: 'EXPIRED' },
    });
  });

  it('notifies banned user via email', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({ id: 'user-1', email: 'user@example.com' });

    await listener.handle({
      aggregateId: 'user-1',
      adminId: 'admin-1',
      reason: 'Spam',
      eventName: 'user.banned',
      occurredAt: new Date(),
    });

    expect(mockCommandBus.execute).toHaveBeenCalledWith(
      expect.objectContaining({
        userId: 'user-1',
        channel: 'EMAIL',
        templateKey: 'user.banned',
        templateData: { reason: 'Spam' },
      }),
    );
  });

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

    await listener.handle({
      aggregateId: 'user-1',
      adminId: 'admin-1',
      reason: 'Vi phạm',
      eventName: 'user.banned',
      occurredAt: new Date(),
    });

    expect(mockPrisma.listing.updateMany).toHaveBeenCalled();
    expect(mockCommandBus.execute).not.toHaveBeenCalled();
  });
});
