import { CreateStudentTool } from './create-student.tool';

function createTool(overrides: Record<string, unknown> = {}) {
  const studentsService = {
    create: jest.fn(async (dto: Record<string, unknown>) => ({ id: 9, ...dto })),
    ...(overrides.studentsService ?? {}),
  };
  const dataSource = {
    getRepository: jest.fn().mockReturnValue({
      findOne: jest.fn().mockResolvedValue({ id: 1, status: 'active', isHost: true }),
    }),
    ...(overrides.dataSource ?? {}),
  };
  const tool = new CreateStudentTool(studentsService as never, dataSource as never);
  return { tool, studentsService, dataSource };
}

describe('CreateStudentTool', () => {
  it('exposes student:create permission and student skill', () => {
    const { tool } = createTool();
    expect(tool.name).toBe('create_student');
    expect(tool.skillKey).toBe('student');
    expect(tool.requiredPermission).toBe('student:create');
  });

  it('rejects forbidden and unknown fields', () => {
    const { tool } = createTool();
    expect(tool.validate({ userId: 1 }).ok).toBe(false);
    expect(tool.validate({ permissions: ['student:create'] }).ok).toBe(false);
    expect(tool.validate({ admin: true }).ok).toBe(false);
  });

  it('requires a valid name and phone', () => {
    const { tool } = createTool();
    expect(tool.validate({}).ok).toBe(false);
    expect(tool.validate({ name: '' }).ok).toBe(false);
    expect(tool.validate({ name: '张三', phone: '123' }).ok).toBe(false);
    expect(tool.validate({ name: '张三', phone: '13800138000', gender: 'other' }).ok).toBe(false);
  });

  it('creates student under the default host organization', async () => {
    const { tool, studentsService } = createTool();
    const result = await tool.execute(
      { name: '张三', phone: '13800138000', gender: 'male', studentNo: 'T001' },
      {} as never,
    );
    expect(studentsService.create).toHaveBeenCalledWith({
      name: '张三',
      phone: '13800138000',
      gender: 'male',
      studentNo: 'T001',
      idNumber: undefined,
      organizationId: 1,
    });
    expect(result).toEqual({
      id: 9,
      name: '张三',
      studentNo: 'T001',
      message: '学生已创建',
    });
    expect(JSON.stringify(result)).not.toContain('13800138000');
  });

  it('uses explicit organizationId when provided', async () => {
    const { tool, studentsService } = createTool();
    await tool.execute({ name: '李四', organizationId: 3 }, {} as never);
    expect(studentsService.create).toHaveBeenCalledWith(
      expect.objectContaining({ organizationId: 3 }),
    );
  });
});
