import { BadRequestException } from '@nestjs/common';
import { StudentsService } from './students.service';

const student = { id: 1, name: '张三', status: 'archived' };

const createService = (overrides?: {
  student?: Record<string, unknown>;
  counts?: Record<string, number>;
}) => {
  const counts = overrides?.counts ?? {};
  const countFor = (key: string) => jest.fn().mockResolvedValue(counts[key] ?? 0);
  const repo = {
    findOne: jest.fn().mockResolvedValue(overrides?.student ?? student),
    delete: jest.fn().mockResolvedValue({ affected: 1 }),
    find: jest.fn().mockResolvedValue([overrides?.student ?? student]),
  };
  const occupancyCount = countFor('occupancy');
  const service = new StudentsService(
    repo as never,
    { count: countFor('classStudent') } as never,
    {} as never,
    { count: countFor('attendance') } as never,
    {} as never,
    {} as never,
    { count: countFor('profile') } as never,
    { count: countFor('enrollment') } as never,
    { count: countFor('examScore') } as never,
    { count: countFor('learningRecord') } as never,
    { count: countFor('result') } as never,
    { count: occupancyCount } as never,
    { count: countFor('personalExpense') } as never,
    { count: countFor('bill') } as never,
    { count: countFor('deposit') } as never,
    { count: countFor('attachment') } as never,
    { count: countFor('dingMapping') } as never,
    { count: countFor('wallet') } as never,
    { count: countFor('inspectionDetail') } as never,
  );
  return { service, repo, occupancyCount };
};

describe('StudentsService.purge', () => {
  it('rejects students that are not archived', async () => {
    const { service, repo } = createService({ student: { id: 1, name: '张三', status: 'active' } });
    await expect(service.purge(1)).rejects.toThrow(
      new BadRequestException('仅已归档学生可以永久删除，请先归档'),
    );
    expect(repo.delete).not.toHaveBeenCalled();
  });

  it('rejects students with any reference', async () => {
    const { service, repo } = createService({ counts: { occupancy: 2 } });
    await expect(service.purge(1)).rejects.toThrow(
      new BadRequestException('该学生存在关联数据（入住记录），无法永久删除'),
    );
    expect(repo.delete).not.toHaveBeenCalled();
  });

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

  it('batch purge returns deleted and skipped counts', async () => {
    const { service, repo, occupancyCount } = createService();
    repo.find = jest.fn().mockResolvedValue([
      { id: 1, name: '甲', status: 'archived' },
      { id: 2, name: '乙', status: 'archived' },
      { id: 3, name: '丙', status: 'active' },
    ]);
    occupancyCount.mockResolvedValueOnce(1).mockResolvedValue(0);
    const result = await service.batchPurge([1, 2, 3]);
    expect(result).toMatchObject({ deleted: 1, skipped: 2 });
    expect(repo.delete).toHaveBeenCalledWith(2);
  });
});
