package com.yonge.cooleshow.biz.dal.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.dao.StudentDao;
import com.yonge.cooleshow.biz.dal.dao.SubjectDao;
import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
import com.yonge.cooleshow.biz.dal.entity.ImGroup;
import com.yonge.cooleshow.biz.dal.entity.ImGroupMember;
import com.yonge.cooleshow.biz.dal.entity.Student;
import com.yonge.cooleshow.biz.dal.entity.Subject;
import com.yonge.cooleshow.biz.dal.entity.Teacher;
import com.yonge.cooleshow.biz.dal.entity.TenantGroup;
import com.yonge.cooleshow.biz.dal.entity.TenantGroupAlbum;
import com.yonge.cooleshow.biz.dal.entity.TenantStaff;
import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
import com.yonge.cooleshow.biz.dal.enums.ImGroupMemberRoleType;
import com.yonge.cooleshow.biz.dal.enums.ImGroupType;
import com.yonge.cooleshow.biz.dal.mapper.TenantGroupAlbumMapper;
import com.yonge.cooleshow.biz.dal.mapper.TenantGroupMapper;
import com.yonge.cooleshow.biz.dal.service.ImGroupMemberService;
import com.yonge.cooleshow.biz.dal.service.ImGroupService;
import com.yonge.cooleshow.biz.dal.service.SysUserService;
import com.yonge.cooleshow.biz.dal.service.TenantGroupService;
import com.yonge.cooleshow.biz.dal.service.im.ImGroupCoreService;
import com.yonge.cooleshow.biz.dal.vo.StudentVo;
import com.yonge.cooleshow.biz.dal.wrapper.StudentWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.TenantGroupAlbumWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.TenantGroupWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.mybatis.support.PageUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 机构小组表
 * 2023-10-11 09:24:50
 */
@Slf4j
@Service
public class TenantGroupServiceImpl extends ServiceImpl<TenantGroupMapper, TenantGroup> implements TenantGroupService {

    @Autowired
    private ImGroupService imGroupService;
    @Autowired
    private ImGroupCoreService imGroupCoreService;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private ImGroupMemberService imGroupMemberService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private TenantGroupAlbumMapper tenantGroupAlbumMapper;

    /**
     * 查询详情
     *
     * @param id 详情ID
     * @return TenantGroup
     */
    @Override
    public TenantGroup detail(Long id) {

        return baseMapper.selectById(id);
    }

    /**
     * 分页查询
     *
     * @param page  IPage<TenantGroup>
     * @param query TenantGroupWrapper.TenantGroupQuery
     * @return IPage<TenantGroup>
     */
    @Override
    public IPage<TenantGroupWrapper.TenantGroup> selectPage(IPage<TenantGroupWrapper.TenantGroup> page,
                                                            TenantGroupWrapper.TenantGroupQuery query) {

        IPage<TenantGroupWrapper.TenantGroup> iPage = page.setRecords(baseMapper.selectPage(page, query));
        List<TenantGroupWrapper.TenantGroup> records = iPage.getRecords();
        // 设置小组成员数量
        if (!records.isEmpty()) {
            List<Long> groupIdList =
                    records.stream().map(TenantGroupWrapper.TenantGroup::getId).collect(Collectors.toList());
            List<StudentWrapper.UserCount> userCounts = studentDao.countStudentByTenantGroupIds(query.getTenantId(),
                    groupIdList);
            Map<Long, Integer> groupBy =
                    userCounts.stream().collect(Collectors.toMap(StudentWrapper.UserCount::getTenantGroupId
                            , StudentWrapper.UserCount::getCount));

            List<String> imGroupId = records.stream().map(TenantGroupWrapper.TenantGroup::getImGroupId)
                    .filter(Objects::nonNull).collect(Collectors.toList());
            List<String> existImgGroupIds = new ArrayList<>();
            if (!imGroupId.isEmpty()) {
                List<String> imgGroupIds = imGroupService.lambdaQuery()
                        .in(ImGroup::getId, imGroupId)
                        .list().stream().map(ImGroup::getId).collect(Collectors.toList());
                existImgGroupIds.addAll(imgGroupIds);
            }
            List<Long> adminIdList = records.stream().map(TenantGroupWrapper.TenantGroup::getAdminId).distinct().collect(Collectors.toList());
            Map<Long, com.yonge.cooleshow.biz.dal.entity.SysUser> mapByIds = sysUserService.getMapByIds(adminIdList);

            String ids = records.stream().map(TenantGroupWrapper.TenantGroup::getId).map(String::valueOf).collect(Collectors.joining(","));
            Map<Long, Integer> countByGroupId = tenantGroupAlbumMapper.countGroupAlbumByGroupId(ids).stream().collect(Collectors.toMap(TenantGroupAlbumWrapper.TenantGroupAlbumCount::getTenantGroupId
                    , TenantGroupAlbumWrapper.TenantGroupAlbumCount::getCount));

            for (TenantGroupWrapper.TenantGroup record : records) {
                record.setGroupUserCount(groupBy.getOrDefault(record.getId(), 0));
                record.setImGroupExist(existImgGroupIds.contains(record.getImGroupId()));
                if (mapByIds.containsKey(record.getAdminId())) {
                    record.setAdminName(mapByIds.get(record.getAdminId()).getUsername());
                }
                record.setAlbumCount(countByGroupId.getOrDefault(record.getId(), 0));
            }
        }
        return iPage;
    }

    /**
     * 添加
     *
     * @param tenantGroup TenantGroupWrapper.TenantGroup
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(TenantGroupWrapper.TenantGroup tenantGroup, Boolean imGroupCreate) {
        TenantGroup entity = JSON.parseObject(tenantGroup.jsonString(), TenantGroup.class);
        Integer count = this.lambdaQuery()
                .eq(TenantGroup::getTenantId, tenantGroup.getTenantId())
                .eq(TenantGroup::getName, entity.getName())
                .count();
        if (count > 0) {
            throw new BizException("小组名称已存在");
        }
        Long adminId = tenantGroup.getAdminId();
        Teacher teacher = teacherDao.selectById(adminId);
        if (!tenantGroup.getTenantId().equals(teacher.getTenantId())) {
            throw new BizException("负责人机构已经变更，请重新选择");
        }
        List<Long> userIds = tenantGroup.getUserIds();
        checkStudent(tenantGroup.getTenantId(), userIds,null);

        this.save(entity);
        if (adminId != null && Boolean.TRUE.equals(imGroupCreate)) {
            // 建群
            try {
                ImGroupWrapper.ImGroup imGroup = new ImGroupWrapper.ImGroup();
                imGroup.setId(IdWorker.getId());
                imGroup.setCreateBy(tenantGroup.getAdminId());
                imGroup.setType(ImGroupType.ORG.getCode());
                imGroup.setName(tenantGroup.getName());
                String imGroupId = imGroupService.create(imGroup);
                entity.setImGroupId(imGroupId);
                this.updateById(entity);
            } catch (Exception e) {
                log.error("创建机构小组群失败", e);
                throw new BizException("创建机构小组群失败");
            }
            // 加群成员
            if (CollectionUtils.isNotEmpty(userIds)) {
                try {
                    imGroupService.addGroupMember(entity.getImGroupId(), new HashSet<>(userIds));
                } catch (Exception e) {
                    log.error("加入机构小组群失败", e);
                    throw new BizException("加入机构小组群失败");
                }
            }
        }
        // 加群成员
        if (CollectionUtils.isNotEmpty(userIds)) {
            studentDao.update(null, Wrappers.<Student>lambdaUpdate()
                    .in(Student::getUserId, userIds)
                    .eq(Student::getTenantId, tenantGroup.getTenantId())
                    .set(Student::getTenantGroupId, entity.getId()));
        }
        return true;
    }

    /**
     * 更新
     *
     * @param tenantGroup TenantGroupWrapper.TenantGroup
     * @return Boolean
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean update(TenantGroupWrapper.TenantGroup tenantGroup, Boolean imGroupCreate) {
        TenantGroup oldGroup = this.getById(tenantGroup.getId());

        Integer count = this.lambdaQuery()
                .ne(TenantGroup::getId, tenantGroup.getId())
                .eq(TenantGroup::getTenantId, tenantGroup.getTenantId())
                .eq(TenantGroup::getName, tenantGroup.getName())
                .count();
        if (count > 0) {
            throw new BizException("小组名称已经存在");
        }

        Long adminId = tenantGroup.getAdminId();
        Teacher teacher = teacherDao.selectById(adminId);
        if (!tenantGroup.getTenantId().equals(teacher.getTenantId())) {
            throw new BizException("负责人机构已经变更，请重新选择");
        }
        checkStudent(tenantGroup.getTenantId(), tenantGroup.getUserIds(),tenantGroup.getId());

        TenantGroup entity = JSON.parseObject(tenantGroup.jsonString(), TenantGroup.class);
        entity.setImGroupId(oldGroup.getImGroupId());
        // 是否建群
        if (Boolean.TRUE.equals(imGroupCreate)) {
            String oldImGroupId = Optional.ofNullable(oldGroup.getImGroupId()).orElse("-1");
            ImGroup imGroup = imGroupService.getById(oldImGroupId);
            // 群被删除过，并且需要重新建群
            if (imGroup == null) {
                String imGroupId = createImGroup(entity.getAdminId(), tenantGroup.getName());
                entity.setImGroupId(imGroupId);

                // 添加群成员
                List<Long> userIds = tenantGroup.getUserIds();
                if (CollectionUtils.isNotEmpty(userIds)) {
                    // 加群成员
                    try {
                        imGroupService.addGroupMember(imGroupId, new HashSet<>(userIds));
                    } catch (Exception e) {
                        log.error("加入机构小组群失败", e);
                        throw new BizException("加入机构小组群失败");
                    }
                }
                studentDao.update(null, Wrappers.<Student>lambdaUpdate()
                        .in(Student::getUserId, userIds)
                        .eq(Student::getTenantId, tenantGroup.getTenantId())
                        .set(Student::getTenantGroupId, entity.getId()));
            }
        }
        // 修改小组负责人，调整群主，更换群主需要新的群主为该群成员
        changeGroupOwner(oldGroup, entity);
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Student::getTenantId, tenantGroup.getTenantId())
                .eq(Student::getTenantGroupId, tenantGroup.getId());
        List<Long> oldGroupUsers = studentDao.selectList(queryWrapper).stream().map(Student::getUserId)
                .collect(Collectors.toList());

        List<Long> newGroupUsers = tenantGroup.getUserIds();

        List<Long> removeGroupUsers = oldGroupUsers.stream()
                .filter(next -> !newGroupUsers.contains(next)).collect(Collectors.toList());
        // 移除的群成员，退群
//        ImGroup imGroup = imGroupService.getById(Optional.ofNullable(entity.getImGroupId()).orElse("-1"));
        if (!removeGroupUsers.isEmpty()) {
//            if (imGroup != null) {
//                try {
//                    for (Long removeUserId : removeGroupUsers) {
//                        imGroupCoreService.groupQuit(removeUserId, ClientEnum.STUDENT.getCode(),
//                                oldGroup.getImGroupId(),
//                                true);
//                    }
//                } catch (Exception e) {
//                    log.error("群成员移出群失败", e);
//                    throw new BizException("群成员移出群失败");
//                }
//            }
            studentDao.update(null, Wrappers.<Student>lambdaUpdate()
                    .in(Student::getUserId, removeGroupUsers)
                    .eq(Student::getTenantId, tenantGroup.getTenantId())
                    .set(Student::getTenantGroupId, -1L));
        }
        // 新增的群成员
        List<Long> newAddGroupUsers = newGroupUsers.stream().filter(next -> !oldGroupUsers.contains(next))
                .collect(Collectors.toList());
        if (!newAddGroupUsers.isEmpty()) {
            // 加群成员
//            if (imGroup != null) {
//                try {
//                    imGroupService.addGroupMember(oldGroup.getImGroupId(), new HashSet<>(newAddGroupUsers));
//                } catch (Exception e) {
//                    log.error("加入机构小组群失败", e);
//                    throw new BizException("加入机构小组群失败");
//                }
//            }
            studentDao.update(null, Wrappers.<Student>lambdaUpdate()
                    .in(Student::getUserId, newAddGroupUsers)
                    .eq(Student::getTenantId, tenantGroup.getTenantId())
                    .set(Student::getTenantGroupId, entity.getId()));
        }
        return this.updateById(entity);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(Long id) {
        TenantGroup group = this.getById(id);
        if (group == null) {
            throw new BizException("机构小组不存在");
        }
        String imGroupId = group.getImGroupId();
        if (imGroupId != null) {
            ImGroup imGroup = imGroupService.getById(imGroupId);
            if (imGroup != null) {
                try {
                    imGroupCoreService.groupDismiss(imGroupId);
                } catch (Exception e) {
                    log.error("解散群失败", e);
                }
            }
        }
        studentDao.update(null, Wrappers.<Student>lambdaUpdate()
                .eq(Student::getTenantId, group.getTenantId())
                .eq(Student::getTenantGroupId, id)
                .set(Student::getTenantGroupId, -1L));

        tenantGroupAlbumMapper.update(null, Wrappers.<TenantGroupAlbum>lambdaUpdate()
                .set(TenantGroupAlbum::getDelFlag, true)
                .eq(TenantGroupAlbum::getTenantGroupId, id));
        return removeById(id);
    }

    /**
     * 查询机构小组群成员
     *
     * @param tenantId      机构ID
     * @param tenantGroupId 机构小组ID
     * @return 机构小组成员列表
     */
    @Override
    public List<TenantGroupWrapper.TenantGroupMember> queryGroupMember(Long tenantId, Long tenantGroupId) {
        StudentSearch studentSearch = new StudentSearch();
        studentSearch.setTenantId(tenantId);
        studentSearch.setTenantGroupId(tenantGroupId.toString());
        studentSearch.setRows(9999);
        studentSearch.setPage(1);
        List<StudentVo> studentVos = studentDao.selectPage(PageUtil.getPage(studentSearch), studentSearch);
        if (studentVos.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, String> subjectIdNameMap = new HashMap<>();
        List<String> subjectIds = studentVos.stream().map(Student::getSubjectId).filter(StringUtils::isNotEmpty)
                .distinct().collect(Collectors.toList());

        if (!subjectIds.isEmpty()) {
            List<Subject> subject = subjectDao.findBySubjectByIdList(String.join(",", subjectIds));
            Map<String, String> map = subject.stream().collect(Collectors.toMap(next -> next.getId().toString(),
                    Subject::getName));
            subjectIdNameMap.putAll(map);
        }


        return studentVos.stream().map(next -> {
            TenantGroupWrapper.TenantGroupMember member = new TenantGroupWrapper.TenantGroupMember();
            member.setUserId(next.getUserId());
            member.setTenantId(next.getTenantId());
            member.setName(next.getUsername());
            member.setGender(next.getGender());
            member.setBirthdate(next.getBirthdate());
            member.setPhone(next.getPhone());
            member.setAvatar(next.getAvatar());
            member.setSubjectId(next.getSubjectId());
            member.setSubjectName(subjectIdNameMap.getOrDefault(next.getSubjectId(), ""));
            return member;
        }).collect(Collectors.toList());
    }

    /**
     * 小组交接
     *
     * @param adjustTenantGroup 入参
     * @return 成功/失败
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean adjustTenantGroup(TenantGroupWrapper.AdjustTenantGroup adjustTenantGroup) {
        Long teacherId = adjustTenantGroup.getTeacherId();
        Teacher teacher = teacherDao.selectById(teacherId);
        if (teacher == null) {
            throw new BizException("移交的老师不存在");
        }
        List<TenantGroupWrapper.AdjustTenantGroupDetail> details = adjustTenantGroup.getAdjustTenantGroupDetails();
        if (details.isEmpty()) {
            throw new BizException("未选择移交信息");
        }
        List<Long> tenantGroupIds =
                details.stream().map(TenantGroupWrapper.AdjustTenantGroupDetail::getTenantGroupId).collect(Collectors.toList());
        List<TenantGroup> tenantGroups = this.lambdaQuery().in(TenantGroup::getId, tenantGroupIds).list();
        Map<Long, String> groupBy = tenantGroups.stream().filter(next -> next.getImGroupId() != null)
                .collect(Collectors.toMap(TenantGroup::getId, TenantGroup::getImGroupId));
        for (TenantGroupWrapper.AdjustTenantGroupDetail detail : details) {
            Long toTeacher = detail.getTeacherId();
            if (teacherId.equals(toTeacher) && Boolean.FALSE.equals(detail.getDismiss())) {
                continue;
            }
            String imGroupId = groupBy.get(detail.getTenantGroupId());
            ImGroup imGroup = imGroupService.getById(Optional.ofNullable(imGroupId).orElse("-1"));
            if (toTeacher != null) {
                // 更换群主
                if (imGroup != null) {
                    // 新负责人加入群
                    try {
                        SysUser newTeacher = sysUserService.getByUserId(toTeacher);
                        ImGroupMember imGroupMember = new ImGroupMember();
                        imGroupMember.setGroupId(imGroupId);
                        imGroupMember.setUserId(toTeacher);
                        imGroupMember.setRoleType(ImGroupMemberRoleType.TEACHER);
                        imGroupMember.setAvatar(newTeacher.getAvatar());
                        imGroupMember.setNickname(newTeacher.getUsername());
                        imGroupMember.setIsAdmin(true);
                        imGroupMember.setRoleType(ImGroupMemberRoleType.TEACHER);

                        imGroupMemberService.join(Collections.singletonList(imGroupMember), imGroupId);
                    } catch (Exception e) {
                        log.error("负责人加入群失败", e);
                        throw new BizException("负责人加入群失败");
                    }

                    try {
                        imGroupCoreService.changeGroupOwner(imGroupId, String.valueOf(toTeacher),
                                String.valueOf(teacherId));
                        imGroupCoreService.groupQuit(teacherId, ClientEnum.TEACHER.getCode(),
                                imGroupId, true);
                        imGroupService.lambdaUpdate()
                                .set(ImGroup::getCreateBy, toTeacher)
                                .eq(ImGroup::getId, imGroupId);
                    } catch (Exception e) {
                        log.error("移交负责人失败", e);
                        throw new BizException("移交负责人失败");
                    }
                }
                this.lambdaUpdate()
                        .set(TenantGroup::getAdminId, toTeacher)
                        .set(imGroup == null, TenantGroup::getImGroupId, null)
                        .eq(TenantGroup::getId, detail.getTenantGroupId())
                        .update();
            } else if (Boolean.TRUE.equals(detail.getDismiss())) {
                // 解散群
                if (imGroup != null) {
                    try {
                        imGroupCoreService.groupDismiss(imGroupId);
                    } catch (Exception e) {
                        log.error("解散群失败", e);
                        throw new BizException("解散群失败");
                    }
                }
                this.lambdaUpdate()
                        .set(TenantGroup::getAdminId, null)
                        .set(TenantGroup::getImGroupId, null)
                        .eq(TenantGroup::getId, detail.getTenantGroupId())
                        .update();
            }
        }
        return true;
    }

    public String createImGroup(Long groupAdmin, String groupName) {
        try {
            ImGroupWrapper.ImGroup imGroup = new ImGroupWrapper.ImGroup();
            imGroup.setId(IdWorker.getId());
            imGroup.setCreateBy(groupAdmin);
            imGroup.setType(ImGroupType.ORG.getCode());
            imGroup.setName(groupName);
            return imGroupService.create(imGroup);
        } catch (Exception e) {
            log.error("创建机构小组群失败", e);
            throw new BizException("创建机构小组群失败");
        }
    }

    private void changeGroupOwner(TenantGroup oldGroup, TenantGroup newGroup) {
        if (newGroup.getAdminId() == null || newGroup.getAdminId().equals(oldGroup.getAdminId())) {
            return;
        }
        String imGroupId = Optional.ofNullable(newGroup.getImGroupId()).orElse("-1");
        ImGroup imGroup = imGroupService.getById(imGroupId);
        if (imGroup == null) {
            // 群不存在
            return;
        }

        if (!newGroup.getImGroupId().equals(oldGroup.getImGroupId())) {
            // 旧的群被删除了，不需要交换身份
            return;
        }

        ImGroupMember admin = imGroupMemberService.lambdaQuery()
                .eq(ImGroupMember::getGroupId, imGroupId)
                .eq(ImGroupMember::getIsAdmin, true)
                .last("limit 1").one();

        if (admin.getUserId().equals(newGroup.getAdminId())) {
            // 处理交接后群主和小组的负责人一致
            return;
        }

        // 如果新负责人不在群，先加入群
        ImGroupMember groupMember = imGroupMemberService.lambdaQuery()
                .eq(ImGroupMember::getGroupId, newGroup.getImGroupId())
                .eq(ImGroupMember::getRoleType, ImGroupMemberRoleType.TEACHER)
                .eq(ImGroupMember::getUserId, newGroup.getAdminId())
                .eq(ImGroupMember::getIsAdmin, true)
                .last("limit 1").one();
        if (groupMember != null) {
            return;
        }
        // 新负责人加入群
        try {
            SysUser newTeacher = sysUserService.getByUserId(newGroup.getAdminId());
            ImGroupMember imGroupMember = new ImGroupMember();
            imGroupMember.setGroupId(newGroup.getImGroupId());
            imGroupMember.setUserId(newGroup.getAdminId());
            imGroupMember.setRoleType(ImGroupMemberRoleType.TEACHER);
            imGroupMember.setAvatar(newTeacher.getAvatar());
            imGroupMember.setNickname(newTeacher.getUsername());
            imGroupMember.setIsAdmin(true);

            imGroupMemberService.join(Collections.singletonList(imGroupMember), newGroup.getImGroupId());
        } catch (Exception e) {
            log.error("负责人加入群失败", e);
            throw new BizException("负责人加入群失败");
        }

        try {
            imGroupCoreService.changeGroupOwner(imGroupId,
                    String.valueOf(newGroup.getAdminId()),
                    String.valueOf(admin.getUserId()));
            imGroupCoreService.groupQuit(admin.getUserId(), ClientEnum.TEACHER.getCode(), imGroupId, true);
            imGroupService.lambdaUpdate()
                    .set(ImGroup::getCreateBy, newGroup.getAdminId())
                    .eq(ImGroup::getId, imGroupId);
        } catch (Exception e) {
            log.error("更换群主失败", e);
            throw new BizException("更换群主失败");
        }
    }

    public List<Student> queryStudent(Long tenantId, Long tenantGroupId) {
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Student::getTenantId, tenantId)
                .eq(Student::getTenantGroupId, tenantGroupId);
        return studentDao.selectList(queryWrapper);
    }

    private void checkStudent(Long tenantId, List<Long> userIds,Long tenantGroupId) {
        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }
        QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .in(Student::getUserId, userIds);
        List<Student> students = studentDao.selectList(queryWrapper);
        if (userIds.size() != students.size()) {
            throw new BizException("参数错误");
        }
        for (Student student : students) {
            if (!tenantId.equals(student.getTenantId())) {
                throw new BizException("学生已经在其他机构");
            }
            Long groupId = student.getTenantGroupId();
            if (groupId != -1L && !groupId.equals(tenantGroupId)) {
                throw new BizException("学生已经在其他小组");
            }
        }
    }
}