import { ProcessScheduledDeletionsHandler } from '../commands/process-scheduled-deletions/process-scheduled-deletions.handler';

describe('ProcessScheduledDeletionsHandler', () => {
  let handler: ProcessScheduledDeletionsHandler;

  const mockPrisma = {
    user: { findMany: vi.fn() },
  };

  const mockCommandBus = { execute: vi.fn() };

  const mockLogger = { log: vi.fn(), warn: vi.fn(), error: vi.fn(), debug: vi.fn(), verbose: vi.fn() };

  beforeEach(() => {
    vi.clearAllMocks();
    handler = new ProcessScheduledDeletionsHandler(
      mockPrisma as any,
      mockCommandBus as any,
      mockLogger as any,
    );
  });

  it('processes all users past their deletion date', async () => {
    mockPrisma.user.findMany.mockResolvedValue([
      { id: 'user-1' },
      { id: 'user-2' },
    ]);
    mockCommandBus.execute.mockResolvedValue({ message: 'ok' });

    const result = await handler.execute();

    expect(result).toEqual({ processedCount: 2 });
    expect(mockCommandBus.execute).toHaveBeenCalledTimes(2);
    expect(mockCommandBus.execute).toHaveBeenCalledWith(
      expect.objectContaining({
        userId: 'user-1',
        adminId: 'SYSTEM',
        reason: 'Scheduled GDPR deletion after 30-day grace period',
      }),
    );
    expect(mockCommandBus.execute).toHaveBeenCalledWith(
      expect.objectContaining({
        userId: 'user-2',
        adminId: 'SYSTEM',
        reason: 'Scheduled GDPR deletion after 30-day grace period',
      }),
    );
  });

  it('returns processedCount', async () => {
    mockPrisma.user.findMany.mockResolvedValue([{ id: 'user-1' }]);
    mockCommandBus.execute.mockResolvedValue({ message: 'ok' });

    const result = await handler.execute();

    expect(result).toEqual({ processedCount: 1 });
  });

  it('handles individual failures gracefully (logs error, continues)', async () => {
    mockPrisma.user.findMany.mockResolvedValue([
      { id: 'user-fail' },
      { id: 'user-ok' },
    ]);
    mockCommandBus.execute
      .mockRejectedValueOnce(new Error('DB down'))
      .mockResolvedValueOnce({ message: 'ok' });

    const result = await handler.execute();

    expect(result).toEqual({ processedCount: 1 });
    expect(mockLogger.error).toHaveBeenCalledWith(
      expect.stringContaining('user-fail'),
      undefined,
      'ProcessScheduledDeletionsHandler',
    );
    expect(mockCommandBus.execute).toHaveBeenCalledTimes(2);
  });

  it('returns 0 when no users to process', async () => {
    mockPrisma.user.findMany.mockResolvedValue([]);

    const result = await handler.execute();

    expect(result).toEqual({ processedCount: 0 });
    expect(mockCommandBus.execute).not.toHaveBeenCalled();
  });
});
