import { ClassesService } from './classes.service';
import { ClassStudent, Student, StudentDingMapping } from '../entities';

describe('ClassesService — DingTalk class import membership lifecycle', () => {
  it('reactivates left memberships and skips active memberships', async () => {
    const left = {
      classId: 3,
      studentId: 8,
      status: 'left',
      joinDate: '2026-01-01',
      leaveDate: '2026-02-01',
    } as ClassStudent;
    const active = { classId: 3, studentId: 9, status: 'active' } as ClassStudent;
    const manager = {
      findOne: jest.fn().mockResolvedValue({ id: 3 }),
      find: jest.fn().mockImplementation(async (entity: unknown) => {
        if (entity === StudentDingMapping) {
          return [
            { dingUserId: 'd8', studentId: 8 },
            { dingUserId: 'd9', studentId: 9 },
          ];
        }
        if (entity === Student) {
          return [
            { id: 8, name: '学生8', status: 'active' },
            { id: 9, name: '学生9', status: 'active' },
          ];
        }
        if (entity === ClassStudent) return [left, active];
        return [];
      }),
      create: jest.fn().mockImplementation((_entity: unknown, value: object) => value),
      save: jest.fn().mockImplementation(async (_entity: unknown, value: unknown) => value),
    };
    const service = new ClassesService(
      {} as never,
      {} as never,
      {} as never,
      {} as never,
      {} as never,
      {} as never,
      {} as never,
      {} as never,
      { transaction: jest.fn().mockImplementation((work) => work(manager)) } as never,
    );

    const result = await service.batchImportStudents(3, [
      { dingUserId: 'd8', name: '学生8' },
      { dingUserId: 'd9', name: '学生9' },
    ]);

    expect(result).toEqual({ imported: 1, skipped: 1, conflicts: 0 });
    expect(left).toMatchObject({ status: 'active', leaveDate: null });
    expect(left.joinDate).toMatch(/^\d{4}-\d{2}-\d{2}$/);
    expect(manager.save).toHaveBeenCalledWith(ClassStudent, [left]);
  });
});
