import { ForbiddenException } from '@nestjs/common';
import { ClassesService } from './classes.service';

describe('ClassesService — teacher data scope', () => {
  const classRepo = { find: jest.fn() };
  const classStudentRepo = { createQueryBuilder: jest.fn() };
  const classTeacherRepo = { find: jest.fn(), findOne: jest.fn() };

  const service = new ClassesService(
    classRepo as never,
    classStudentRepo as never,
    classTeacherRepo as never,
    {} as never,
    {} as never,
    {} as never,
    {} as never,
  );

  beforeEach(() => jest.clearAllMocks());

  it('returns only class ids assigned to a teacher', async () => {
    classTeacherRepo.find.mockResolvedValue([{ classId: 3 }, { classId: 5 }, { classId: 3 }]);

    await expect(service.getAccessibleClassIds(21, false)).resolves.toEqual([3, 5]);
  });

  it('rejects access to a class outside the teacher assignments', async () => {
    classTeacherRepo.findOne.mockResolvedValue(null);

    await expect(service.assertClassAccess(21, 9, false)).rejects.toBeInstanceOf(
      ForbiddenException,
    );
  });

  it('allows class managers to access any class', async () => {
    await expect(service.assertClassAccess(21, 9, true)).resolves.toBeUndefined();
    expect(classTeacherRepo.findOne).not.toHaveBeenCalled();
  });
});

it('clears denormalized teacher ids when the last teacher for that role is removed', async () => {
  const classRepo = { update: jest.fn() };
  const classTeacherRepo = {
    find: jest
      .fn()
      .mockResolvedValueOnce([{ id: 1, classId: 8, userId: 21 }])
      .mockResolvedValueOnce([]),
    delete: jest.fn().mockResolvedValue({ affected: 1 }),
  };
  const service = new ClassesService(
    classRepo as never,
    {} as never,
    classTeacherRepo as never,
    {} as never,
    {} as never,
    {} as never,
    {} as never,
  );

  await service.removeTeacher(8, 21);

  expect(classRepo.update).toHaveBeenCalledWith(8, {
    headTeacherId: null,
    lifeTeacherId: null,
    academicTeacherId: null,
  });
});
