import { BadRequestException } from '@nestjs/common';
import { RoomsService } from './rooms.service';

describe('RoomsService.purge', () => {
  const createService = (overrides?: {
    room?: Record<string, unknown>;
    occupancyCount?: number;
    expenseCount?: number;
  }) => {
    const room = { id: 1, roomNumber: '101', status: 'archived', ...overrides?.room };
    const repo = {
      findOne: jest.fn().mockResolvedValue(room),
      delete: jest.fn().mockResolvedValue({ affected: 1 }),
      find: jest.fn().mockResolvedValue([room]),
    };
    const occRepo = { count: jest.fn().mockResolvedValue(overrides?.occupancyCount ?? 0) };
    const roomExpRepo = { count: jest.fn().mockResolvedValue(overrides?.expenseCount ?? 0) };
    const service = new RoomsService(
      repo as never,
      occRepo as never,
      roomExpRepo as never,
      {} as never,
      {} as never,
      {} as never,
      {} as never,
    );
    return { service, repo, occRepo, roomExpRepo };
  };

  it('rejects rooms that are not archived', async () => {
    const { service, repo } = createService({ room: { status: 'available' } });
    await expect(service.purge(1)).rejects.toThrow(
      new BadRequestException('仅已归档宿舍可以永久删除，请先归档'),
    );
    expect(repo.delete).not.toHaveBeenCalled();
  });

  it('rejects rooms referenced by occupancies or expenses', async () => {
    const withOccupancy = createService({ occupancyCount: 1 });
    await expect(withOccupancy.service.purge(1)).rejects.toThrow(
      new BadRequestException('该宿舍存在入住记录，无法永久删除'),
    );
    expect(withOccupancy.repo.delete).not.toHaveBeenCalled();

    const withExpense = createService({ expenseCount: 1 });
    await expect(withExpense.service.purge(1)).rejects.toThrow(
      new BadRequestException('该宿舍存在宿舍费用，无法永久删除'),
    );
    expect(withExpense.repo.delete).not.toHaveBeenCalled();
  });

  it('deletes an archived room with no references', async () => {
    const { service, repo } = createService();
    await expect(service.purge(1)).resolves.toEqual({ message: '已永久删除宿舍（不可恢复）' });
    expect(repo.delete).toHaveBeenCalledWith(1);
  });

  it('batch purge skips referenced rooms', async () => {
    const { service, repo, occRepo } = createService();
    repo.find = jest.fn().mockResolvedValue([
      { id: 1, roomNumber: '101', status: 'archived' },
      { id: 2, roomNumber: '102', status: 'archived' },
    ]);
    occRepo.count
      .mockResolvedValueOnce(1)
      .mockResolvedValueOnce(0);
    const result = await service.batchPurge([1, 2]);
    expect(result).toMatchObject({ deleted: 1, skipped: 1 });
    expect(repo.delete).toHaveBeenCalledWith(2);
  });
});
