import { NotFoundException, ValidationException } from '@modules/shared';
import { CancelUserDeletionCommand } from '../commands/cancel-user-deletion/cancel-user-deletion.command';
import { CancelUserDeletionHandler } from '../commands/cancel-user-deletion/cancel-user-deletion.handler';

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

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

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

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

  it('cancels pending deletion and reactivates user', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({
      id: 'user-1',
      deletedAt: null,
      deletionScheduledAt: new Date(),
    });
    mockPrisma.user.update.mockResolvedValue({});

    const result = await handler.execute(new CancelUserDeletionCommand('user-1'));

    expect(result).toEqual({ message: 'Đã hủy yêu cầu xóa tài khoản' });
    expect(mockPrisma.user.update).toHaveBeenCalledWith({
      where: { id: 'user-1' },
      data: { deletionScheduledAt: null, isActive: true },
    });
  });

  it('throws NotFoundException if user not found', async () => {
    mockPrisma.user.findUnique.mockResolvedValue(null);

    await expect(
      handler.execute(new CancelUserDeletionCommand('missing')),
    ).rejects.toThrow(NotFoundException);
  });

  it('throws ValidationException if user already permanently deleted', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({
      id: 'user-1',
      deletedAt: new Date(),
      deletionScheduledAt: null,
    });

    await expect(
      handler.execute(new CancelUserDeletionCommand('user-1')),
    ).rejects.toThrow(ValidationException);
  });

  it('throws ValidationException if no pending deletion', async () => {
    mockPrisma.user.findUnique.mockResolvedValue({
      id: 'user-1',
      deletedAt: null,
      deletionScheduledAt: null,
    });

    await expect(
      handler.execute(new CancelUserDeletionCommand('user-1')),
    ).rejects.toThrow(ValidationException);
  });
});
