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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.microsvc.toolkit.middleware.common.http.ImageUtil;
import com.microsvc.toolkit.middleware.im.ImPluginContext;
import com.microsvc.toolkit.middleware.im.message.GroupMemberWrapper;
import com.microsvc.toolkit.middleware.im.message.MessageWrapper;
import com.microsvc.toolkit.middleware.im.message.TencentRequest;
import com.microsvc.toolkit.middleware.im.properties.ImConfigProperties;
import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginContext;
import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginService;
import com.microsvc.toolkit.middleware.rtc.impl.TencentCloudRTCPlugin;
import com.microsvc.toolkit.middleware.rtc.message.ImGroupMemberWrapper;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.auth.config.AppGlobalServiceConfig;
import com.yonge.cooleshow.biz.dal.dao.CourseScheduleStudentPaymentDao;
import com.yonge.cooleshow.biz.dal.dao.ImGroupDao;
import com.yonge.cooleshow.biz.dal.dao.ImGroupMemberAuditDao;
import com.yonge.cooleshow.biz.dal.dao.TeacherDao;
import com.yonge.cooleshow.biz.dal.dto.BasicUserInfo;
import com.yonge.cooleshow.biz.dal.dto.ImGroupResultDto;
import com.yonge.cooleshow.biz.dal.dto.ImGroupSearchDto;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.dto.search.StudentSearch;
import com.yonge.cooleshow.biz.dal.dto.search.TeacherSearch;
import com.yonge.cooleshow.biz.dal.entity.*;
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.enums.RoleEnum;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.entity.CourseGroup;
import com.yonge.cooleshow.biz.dal.entity.ImGroup;
import com.yonge.cooleshow.biz.dal.entity.ImGroupMember;
import com.yonge.cooleshow.biz.dal.entity.ImHistoryMessage;
import com.yonge.cooleshow.biz.dal.entity.StudentStar;
import com.yonge.cooleshow.biz.dal.entity.Teacher;
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.service.CourseGroupService;
import com.yonge.cooleshow.biz.dal.service.ImGroupMemberService;
import com.yonge.cooleshow.biz.dal.service.ImGroupService;
import com.yonge.cooleshow.biz.dal.service.ImUserFriendService;
import com.yonge.cooleshow.biz.dal.service.StudentStarService;
import com.yonge.cooleshow.biz.dal.service.SysUserService;
import com.yonge.cooleshow.biz.dal.service.TeacherService;
import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
import com.yonge.cooleshow.biz.dal.service.im.ImGroupCoreService;
import com.yonge.cooleshow.biz.dal.support.IMHelper;
import com.yonge.cooleshow.biz.dal.vo.StudentVo;
import com.yonge.cooleshow.biz.dal.vo.TeacherVo;
import com.yonge.cooleshow.biz.dal.wrapper.ImHistoryMessageWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupWrapper;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.entity.UploadReturnBean;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.util.ThreadPool;
import com.yonge.toolset.utils.date.DateUtil;
import io.rong.RongCloud;
import io.rong.methods.message.history.History;
import com.yonge.toolset.mybatis.support.PageUtil;
import io.rong.RongCloud;
import io.rong.methods.message.history.History;
import io.rong.models.Result;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.MessageFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

/**
 * 即时通讯群组(ImGroup)表服务实现类
 *
 * @author zx
 * @since 2022-03-22 10:45:57
 */
@Service("imGroupService")
public class ImGroupServiceImpl extends ServiceImpl<ImGroupDao, ImGroup> implements ImGroupService {

    private final static Logger log = LoggerFactory.getLogger(ImGroupServiceImpl.class);

    @Resource
    private CourseGroupService courseGroupService;
    @Resource
    private ImUserFriendService imUserFriendService;
    @Resource
    private ImGroupMemberService imGroupMemberService;
    @Resource
    private ImGroupMemberAuditDao imGroupMemberAuditDao;
    @Resource
    private SysUserService sysUserService;
    @Autowired
    private ImGroupService imGroupService;
    @Autowired
    private TeacherService teacherService;
    @Resource
    private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
    @Autowired
    private AppGlobalServiceConfig appGlobalServiceConfig;
    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private StudentStarService studentStarService;

    @Value("${cn.rongcloud.im.appkey}")
    private String appKey;
    @Value("${cn.rongcloud.im.secret}")
    private String appSecret;

    @Autowired
    private CustomerServiceBatchSendingService customerServiceBatchSendingService;


    @Autowired
    private ImPluginContext imPluginContext;

    @Autowired
    private ImConfigProperties imConfig;

    @Autowired
    private IMHelper imHelper;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    @Autowired
    private RTCRoomPluginContext rtcRoomPluginContext;

    @Autowired
    private UploadFileService uploadFileService;

    @Autowired
    private ImGroupCoreService imGroupCoreService;

    @Autowired
    private TeacherDao teacherDao;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private StudentService studentService;

    @Override
    public ImGroupDao getDao() {
        return this.baseMapper;
    }


    /**
     * IM 用户注册
     *
     * @param userId   用户ID
     * @param username 用户名
     * @param avatar   用户头象
     * @return IM聊天Token
     */
    @Override
    public ImGroupWrapper.ImUserInfo register(String userId, ClientEnum clientType, String username, String avatar) throws Exception {
        return imGroupCoreService.register(userId,clientType.name(), username, avatar);
    }


    /**
     * IM 用户注册
     *
     * @param userId 用户Id
     * @return String
     */
    @Override
    public String getImUserId(String userId, String clientType) {
        String imUserId = userId;
        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !userId.startsWith(imConfig.getAppPrefix())) {
            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId, clientType);
        }
        return imUserId;
    }

    @Override
    public String getImUserId(Long userId, RoleEnum userRole) {
        String imUserId = String.valueOf(userId);
        String clientType = "STUDENT";
        if(userRole.RoleTeacher == userRole){
            clientType = "TEACHER";
        }
        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !imUserId.startsWith(imConfig.getAppPrefix())) {
            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId.toString(), clientType);
        }
        return imUserId;
    }

    @Override
    public String getImUserId(Long userId, ClientEnum clientEnum) {
        String imUserId = String.valueOf(userId);
        String clientType = "STUDENT";
        if(clientEnum.TEACHER == clientEnum){
            clientType = "TEACHER";
        }
        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && !imUserId.startsWith(imConfig.getAppPrefix())) {
            imUserId = MessageFormat.format("{0}_{1}_{2}", imConfig.getAppPrefix(), userId.toString(), clientType);
        }
        return imUserId;
    }


    /**
     * 解析IM用户规则
     *
     * @param imUserId IM用户Id
     * @return String
     */
    @Override
    public String analysisImUserId(String imUserId) {
        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && imUserId.startsWith(imConfig.getAppPrefix())) {
            return imUserId.replace(imConfig.getAppPrefix() + "_", "").split("_")[0];
        }
        return imUserId;
    }


    /**
     * 检测imUserid
     *
     * @param imUserId IM用户Id
     * @return String
     */
    @Override
    public boolean checkImUserId(String imUserId) {
       return imUserId.startsWith(imConfig.getAppPrefix());
    }

    @Override
    public String analysisImUserClient(String imUserId) {
        if (StringUtils.isNotBlank(imConfig.getAppPrefix()) && imUserId.startsWith(imConfig.getAppPrefix())) {
            imUserId =  imUserId.replace(imConfig.getAppPrefix() + "_", "");
            String[] s = imUserId.split("_");
            if (s.length > 1) {
                return imUserId.replace(s[0] + "_", "");
            }
        }
        return imUserId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String create(ImGroupWrapper.ImGroup imGroup) throws Exception {
        Date now = new Date();
        if (imGroup.getType() == null) {
            imGroup.setType(ImGroupType.FAN.getCode());
        }
        imGroup.setMemberNum(1);
        imGroup.setCreateTime(now);
        imGroup.setUpdateTime(now);
        imGroup.setImg(sysConfigService.findConfigValue(SysConfigConstant.ICON_FANS_GROUP_DEFAULT));
        ImGroup group = JSON.parseObject(JSON.toJSONString(imGroup), ImGroup.class);
        String groupId = createImGroup(group);
        if (!imGroup.getStudentIdList().isEmpty()) {
            addGroupMember(groupId,imGroup.getStudentIdList());
        }
        return groupId;


//        String imGroupId = UUID.randomUUID() + imGroup.getType().getCode();
//        imGroup.setId(imGroupId);
//        this.baseMapper.insert(imGroup);
//        //处理本地群成员列表
//        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(),
//                true, ImGroupMemberRoleType.TEACHER);
//        //创建融云群
//        this.rtcCreate(imGroup.getCreateBy(), imGroupId, imGroup.getName(),imGroup.getImg());
//        //加入融云群
//        imGroupMemberService.join(groupMembers, imGroupId);
    }

    private String createImGroup(ImGroup imGroup) throws Exception {
        ImGroupWrapper.ImGroup group =JSON.parseObject(JSON.toJSONString(imGroup), ImGroupWrapper.ImGroup.class);

        //记录群成员
        BasicUserInfo basicUserInfo = teacherDao.getBasicUserInfo(imGroup.getCreateBy());
        GroupMemberWrapper.ImGroupMember groupMember = GroupMemberWrapper.ImGroupMember
                .builder()
                .userId(imGroup.getCreateBy())
                .clientType(ClientEnum.TEACHER.getCode())
                .avatar(basicUserInfo.getAvatar())
                .nickname(basicUserInfo.getUsername())
                .roleType(ClientEnum.TEACHER.getCode())
                .build();
        return imGroupCoreService.groupCreate(groupMember, group);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addGroupMember(String groupId, Set<Long> studentIdList) throws Exception {
        ImGroup imGroup = this.baseMapper.selectById(groupId);
        if (imGroup == null) {
            throw new BizException("群不存在");
        }
        if (studentIdList.isEmpty()) {
            throw new BizException("添加的群成员不能为空");

        }
        List<ImGroupMember> groupMemberList = imGroupMemberService.initGroupMembers(groupId,
                studentIdList, ImGroupMemberRoleType.STUDENT);
        imGroupMemberService.join(groupMemberList, groupId);

        // 如果是机构群，学生自动添加老师好友
        if (ImGroupType.ORG.equals(imGroup.getType())) {
            List<ImGroupMember> teacherList = imGroupMemberService.lambdaQuery()
                    .eq(ImGroupMember::getGroupId, groupId)
                    .eq(ImGroupMember::getRoleType, ImGroupMemberRoleType.TEACHER)
                    .list();
            teacherList.forEach(teacher -> imUserFriendService.saveUserFriend(teacher.getUserId(), studentIdList));
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String autoCreate(Long courseGroupId, String courseGroupType) throws Exception {
        //获取课程组
        CourseGroup courseGroup = courseGroupService.getById(courseGroupId);
        if (courseGroup.getTeacherId() == null) {
            return null;
        }
        //获取学员列表
        Set<Long> studentIds = courseScheduleStudentPaymentDao.queryStudentIds(courseGroupId, courseGroupType);
        studentIds.removeAll(Collections.singleton(null));
        if (CollectionUtils.isEmpty(studentIds)) {
            return null;
        }
        Date now = new Date();
        Long teacherId = courseGroup.getTeacherId();
        //保存老师学员关联的通讯录xz
        imUserFriendService.saveUserFriend(teacherId, studentIds);

        //创建群聊
        ImGroup imGroup = new ImGroup();
        imGroup.setCreateBy(teacherId);
        imGroup.setAutoPassFlag(false);
        imGroup.setMemberNum(studentIds.size() + 1);
        imGroup.setName(courseGroup.getName());
        imGroup.setType(ImGroupType.COURSE);
        imGroup.setImg(sysConfigService.findConfigValue(SysConfigConstant.ICON_COURSE_GROUP_DEFAULT));
        imGroup.setCreateTime(now);
        imGroup.setUpdateTime(now);
//        String imGroupId = UUID.randomUUID() + imGroup.getType().getCode();
//        imGroup.setId(imGroupId);
        imGroup.setCourseGroupId(courseGroupId);
//        this.baseMapper.insert(imGroup);


        String groupId = createImGroup(imGroup);
//        // 添加学生
        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMembers(groupId, studentIds,
                ImGroupMemberRoleType.STUDENT);
        List<com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupMemberWrapper.ImGroupMember> groupMemberList = Lists.newArrayList();
        for (ImGroupMember groupMember : groupMembers) {
            groupMemberList.add(com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupMemberWrapper.ImGroupMember.builder()
                    .groupId(groupMember.getGroupId())
                    .userId(groupMember.getUserId())
                    .clientType(groupMember.getRoleType().getCode())
                    .avatar(groupMember.getAvatar())
                    .nickname(groupMember.getNickname())
                    .isAdmin(groupMember.getIsAdmin())
                    .imUserId(getImUserId(groupMember.getUserId().toString(), groupMember.getRoleType().getCode()))
                    .roleType(groupMember.getRoleType().getCode())
                    .build());
        }
        imGroupCoreService.saveImGroupMemberList(groupId, groupMemberList);
        //处理本地群成员列表
        // 添加老师
//        List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(),
//                true, ImGroupMemberRoleType.TEACHER);

//        //创建融云群
//        this.rtcCreate(courseGroup.getTeacherId(), imGroupId, imGroup.getName(),imGroup.getImg());
//        //加入融云群
//        imGroupMemberService.join(groupMembers, imGroupId);
        return groupId.toString();
    }


    /**
     * 批量导入用户
     *
     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
     */
    private void registerUser(List<GroupMemberWrapper.ImGroupMember> groupMembers) {
        for (GroupMemberWrapper.ImGroupMember member : groupMembers) {
            // 激活用户帐号为空
            if (StringUtils.isBlank(member.getNickname())) {
                continue;
            }

            try {

                imGroupCoreService.register(member.getUserId().toString(), member.getClientType(), member.getNickname(), member.getAvatar());

            } catch (Exception e) {
                log.error("registerUser member imToken");
            }
        }
    }

    @Override
    public List<GroupMemberWrapper.ImGroupMember> getImGroupMembers(List<ImGroupMember> groupMemberList) {
        return groupMemberList.stream().map(item -> {
            return GroupMemberWrapper.ImGroupMember.builder()
                    .id(item.getId())
                    .groupId(item.getGroupId())
                    .userId(item.getUserId())
                    .clientType(item.getRoleType().getCode())
                    .avatar(item.getAvatar())
                    .nickname(item.getNickname())
                    .isAdmin(item.getIsAdmin())
                    .imUserId(getImUserId(item.getUserId().toString(),item.getRoleType().getCode()))
                    .roleType(item.getRoleType().getCode())
                    .build();
        }).collect(Collectors.toList());
    }


    /**
     * 自动注册用户
     *
     * @param groupMembers List<ImGroupMemberWrapper.ImGroupMember>
     */
    @Override
    public void asyncRegisterUser(List<GroupMemberWrapper.ImGroupMember> groupMembers) {
        com.microsvc.toolkit.common.tools.ThreadPool.getExecutor().submit(() -> registerUser(groupMembers));
    }

    @Override
    public void dismiss(String groupId) throws Exception {
       imGroupCoreService.groupDismiss(groupId);
    }

    @Override
    public List<ImGroup> queryAll(ImGroupSearchDto imGroupSearchDto) {
        return baseMapper.findAll(imGroupSearchDto);
    }

    @Override
    public List<ImGroupResultDto> queryTeacherFun(ImGroupSearchDto imGroupSearchDto) {
        imGroupSearchDto.setUserId(sysUserService.getUserId());
        return baseMapper.queryTeacherFun(imGroupSearchDto);
    }

    @Override
    public ImGroup getByCourseGroupId(Long courseGroupId) {
        return this.lambdaQuery()
                .eq(ImGroup::getCourseGroupId, courseGroupId)
                .last("limit 1")
                .one();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void quit(String groupId, Long userId, ClientEnum clientType,Boolean quit) throws Exception {
        imGroupCoreService.groupQuit(userId, clientType.name(), groupId, quit);
    }

    @Override
    public void setTeacherFansGroup() throws Exception {
        // 查询所有认证老师
        List<Teacher> teacherList = teacherService.lambdaQuery().eq(Teacher::getEntryFlag, 1).list();

        // 遍历给老师创建粉丝群

        for (Teacher teacher : teacherList) {

            // 已经有群的不操作
            Integer count = this.lambdaQuery()
                    .eq(ImGroup::getCreateBy, teacher.getUserId())
                    .eq(ImGroup::getAutoPassFlag, true)
                    .eq(ImGroup::getType, ImGroupType.FAN)
                    .count();
            if (count > 0) {
                continue;
            }

            // 老师用户信息
            SysUser sysUser = sysUserFeignService.queryUserById(teacher.getUserId());
            if (sysUser == null) {
                continue;
            }


            // 查询老师的粉丝，添加到群
            List<StudentStar> list = studentStarService.lambdaQuery()
                    .eq(StudentStar::getTeacherId, teacher.getUserId())
                    .list();
            Set<Long> studentIdList = list.stream().map(StudentStar::getStudentId).collect(Collectors.toSet());


            //创建群聊
            ImGroup imGroup = new ImGroup();
            imGroup.setCreateBy(teacher.getUserId());
            imGroup.setAutoPassFlag(true);
            imGroup.setMemberNum(studentIdList.size() + 1);
            imGroup.setName(sysUser.getUsername() + "的粉丝群");
            imGroup.setType(ImGroupType.FAN);
            imGroup.setCreateTime(new Date());

            imGroup.setImg(sysConfigService.findConfigValue(SysConfigConstant.ICON_FANS_GROUP_DEFAULT));
            imGroup.setUpdateTime(new Date());
            imGroup.setCreateBy(teacher.getUserId());
//            String imGroupId = UUID.randomUUID() + imGroup.getType().getCode();
//            imGroup.setId(imGroupId);
//            this.baseMapper.insert(imGroup);
//            List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMember(imGroupId, imGroup.getCreateBy(),
//                    true, ImGroupMemberRoleType.TEACHER);
//            if (!CollectionUtils.isEmpty(studentIdList)) {
//                groupMembers.addAll(imGroupMemberService.initGroupMembers(imGroupId, studentIdList,
//                        ImGroupMemberRoleType.STUDENT));
//            }
            //创建融云群
            String groupId = createImGroup(imGroup);

            // 添加学生
            List<ImGroupMember> groupMembers = imGroupMemberService.initGroupMembers(groupId, studentIdList,
                    ImGroupMemberRoleType.STUDENT);
            List<com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupMemberWrapper.ImGroupMember> groupMemberList = Lists.newArrayList();
            for (ImGroupMember groupMember : groupMembers) {
                groupMemberList.add(com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupMemberWrapper.ImGroupMember.builder()
                        .groupId(groupMember.getGroupId())
                        .userId(groupMember.getUserId())
                        .clientType(groupMember.getRoleType().getCode())
                        .avatar(groupMember.getAvatar())
                        .nickname(groupMember.getNickname())
                        .isAdmin(groupMember.getIsAdmin())
                        .imUserId(getImUserId(groupMember.getUserId().toString(), groupMember.getRoleType().getCode()))
                        .roleType(groupMember.getRoleType().getCode())
                        .build());
            }
            imGroupCoreService.saveImGroupMemberList(groupId, groupMemberList);
            //加入融云群
//            imGroupMemberService.join(groupMembers, imGroupId);

        }

    }

    /**
     * 用户群组信息
     *
     * @param groupId 群组ID
     * @param userId  用户ID
     * @return ImGroup
     */
    @Override
    public ImGroup findGroupInfoById(String groupId, Long userId) {

        ImGroup group = imGroupService.getById(groupId);

        // 异步执行自动加入群组功能
        ThreadPool.getExecutor().submit(() -> {
            try {

                if (Objects.nonNull(group) && appGlobalServiceConfig.getGroupMemberJoin()) {

                    // 若用户群组存在，判定用户是否拥有老师身份，自动加入群组
                    int count = teacherService.lambdaQuery().eq(Teacher::getUserId, userId).count();

                    // 用户是否已加入该群组
                    ImGroupMember groupMember = imGroupMemberService.lambdaQuery()
                            .eq(ImGroupMember::getGroupId, groupId)
                            .eq(ImGroupMember::getUserId, userId)
                            .eq(ImGroupMember::getRoleType, ImGroupMemberRoleType.STUDENT)
                            .one();

                    if (Objects.nonNull(groupMember)) {

                        String userKey = imGroupService.getImUserId(String.valueOf(userId),
                                ClientEnum.STUDENT.name());
                        RBucket<Object> bucket = redissonClient.getBucket(userKey);
                        if (bucket.isExists()) {
                            return;
                        }

                        // 自动加入该群组
                        imGroupMemberService.join(Lists.newArrayList(groupMember), groupId);

                        Integer numbers = imGroupMemberService.lambdaQuery()
                                .eq(ImGroupMember::getGroupId, groupId)
                                .eq(ImGroupMember::getUserId, userId)
                                .eq(ImGroupMember::getIsAdmin, true)
                                .count();
                        // 拥有老师身份，且非群主时，需要主动退出群聊
                        if (count > 0 && numbers <= 0) {
                            quit(groupId, userId, ClientEnum.TEACHER,true);
                        }

                        // 缓存重新入群标识, 默认有效期为120天
                        bucket.set(userKey, 120, TimeUnit.DAYS);
                    }
                }

            } catch (Exception e) {
                log.error("findGroupInfoById groupId={}, userId={}", group, userId, e);
            }
        });

        return group;
    }



    /**
     * 同步即时通讯聊天记录
     *
     * @param date
     * @return
     */
    @Override
    public Result historyGet(String date) throws Exception {
        return getHistory().get(date);

    }




    @Override
    public void saveImHistoryMessage(File file) {
        ZipInputStream zin = null;
        try {
            zin = new ZipInputStream(new FileInputStream(file), StandardCharsets.UTF_8);
            ZipFile zf = new ZipFile(file);
            ZipEntry ze;
            Set<ImHistoryMessage> historyMessages = new HashSet<>();
            while ((ze = zin.getNextEntry()) != null) {
                BufferedReader br = new BufferedReader(new InputStreamReader(zf.getInputStream(ze)));
                String line;
                while ((line = br.readLine()) != null) {
                    try {
                        historyMessages.add(JSONObject.parseObject(line.substring(line.indexOf("{")),
                                ImHistoryMessage.class));
//						if(historyMessages.size() >= 2000){
//							historyMessageDao.batchInsert(new ArrayList<>(historyMessages),HistoryMessage.class);
//							historyMessages.clear();
//						}
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                br.close();
                break;
            }
            if (historyMessages.size() > 0) {
                ImGroupDao dao = getDao();
                dao.batchInsert(historyMessages.stream().sorted(Comparator.comparing(ImHistoryMessage::getDateTime)).collect(Collectors.toList()));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zin != null) {
                try {
                    zin.closeEntry();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void getAndSaveImHistoryMessage(String date) throws Exception {

        Object o = imGroupService.historyGet(date);
        JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(o));
        if (jsonObject.get("code").equals(200)) {
            String url = jsonObject.getString("url");
            if (!StringUtils.isEmpty(url)) {
                File file = new File(FileUtils.getTempDirectoryPath() + url.substring(url.lastIndexOf("/")));
                URL url1 = new URL(url);
                FileUtils.copyURLToFile(url1, file);
                imGroupService.saveImHistoryMessage(new File(file.getAbsolutePath()));
            }

        }
    }

    @Override
    public List<ImHistoryMessage> getRongYunInfo( int page, int size) {
        int result = (page-1)*size;
        List<ImHistoryMessage> imHistoryMessageslist = getDao().selectAll(result,size);
        return imHistoryMessageslist;
    }

    /**
     * IM导入消息
     */
    @Override
    public void importInfo(List<ImHistoryMessage> info) throws Exception {

        for (ImHistoryMessage i : info) {//判断消息类型
            log.info("消息导入：{}",i);
            try {
                Integer type = i.getTargetType();
                if (type == 1) {
                    //单聊会话
                    MessageWrapper.PrivateImportMessage privateImportMessage = new MessageWrapper.PrivateImportMessage();
                    //2：表示历史消息导入，消息不计入未读计数，且消息不会推送到终端
                    privateImportMessage.setSyncFromOldSystem(2);
                    //设置发送人
                    //根据发送者分场景讨论
                    String id = i.getFromUserId();
                    String imUserId;
                    if (id.contains(":STUDENT")) {
                        String[] split = id.split(":");
                        String userId = split[0];
                        String clientType = split[1];
                        imUserId = getImUserId(userId, clientType);
                    } else {
                        imUserId = getImUserId(id, "TEACHER");
                    }

                    String targetId = i.getTargetId();
                    String targetIdUserId;
                    if (targetId.contains(":STUDENT")) {
                        String[] split = targetId.split(":");
                        String userId = split[0];
                        String clientType = split[1];
                        targetIdUserId = getImUserId(userId, clientType);
                    } else {
                        targetIdUserId = getImUserId(targetId, "TEACHER");
                    }

                    privateImportMessage.setFromAccount(imUserId);
                    //设置接收人
                    privateImportMessage.setToAccount(targetIdUserId);
                    //设置随机数
                    privateImportMessage.setMsgRandom(new Random().nextInt());

                    //设置发送时间
                    String time = i.getDateTime();
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    try {
                        Date date = df.parse(time);
                        long dateTime = date.getTime();
                        dateTime = dateTime / (1000);
                        privateImportMessage.setMsgTimeStamp(dateTime);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }

                    //设置body
                    TencentRequest.MessageBody body = new TencentRequest.MessageBody();
                    List<TencentRequest.MessageBody> list = new ArrayList<>();

                    JSONObject jsonObject = JSONObject.parseObject(i.getContent());
                    if (i.getClassname().equals("RC:TxtMsg")) {
                        //文本
                        TencentRequest.MessageBody body1 = CustomerServiceBatchSendingServiceImpl.getTimTextElem(jsonObject.getString("content"));
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:ImgMsg")) {
                        //图片
                        TencentRequest.MessageBody body1 = CustomerServiceBatchSendingServiceImpl.getTimImageElem(jsonObject.getString("imageUri"));
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:GIFMsg")) {
                        //GIf
                        String remoteUrl = jsonObject.getString("remoteUrl");
                        int gifDataSize = jsonObject.getInteger("gifDataSize");
                        int width = jsonObject.getInteger("width");
                        int height = jsonObject.getInteger("height");
                        TencentRequest.MessageBody body1 = getTimGifElem(remoteUrl, gifDataSize, width, height);
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:HQVCMsg")) {
                        //语音
                        String remoteUrl = jsonObject.getString("remoteUrl");
                        int duration = jsonObject.getInteger("duration");
                        TencentRequest.MessageBody body1 = getTimSoundElem(remoteUrl, duration);
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:FileMsg")) {
                        //文件
                        String fileUrl = jsonObject.getString("fileUrl");
                        String size = jsonObject.getString("size");
                        String name = jsonObject.getString("name");

                        TencentRequest.MessageBody body1 = getTimFileElem(fileUrl, size, name);
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:SightMsg")) {
                        //视频
                        String sightUrl = jsonObject.getString("sightUrl");
                        String size = jsonObject.getString("size");
                        int duration = jsonObject.getInteger("duration");
                        String content = jsonObject.getString("content");
                        TencentRequest.MessageBody body1 = null;
                        try {
                            body1 = getTimVideoFileElem(sightUrl, size, duration, content);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:LBSMsg")) {
                        //位置
                        double latitude = jsonObject.getDouble("latitude");
                        double longitude = jsonObject.getDouble("longitude");
                        String poi = jsonObject.getString("poi");
                        TencentRequest.MessageBody body1 = getTimLocationElem(latitude, longitude, poi);
                        list.add(body1);
                    } else if (i.getClassname().equals("RC:ImgTextMsg")) {
                        //图文
                        TencentRequest.MessageBody body1 = CustomerServiceBatchSendingServiceImpl.getTimTextElem(jsonObject.getString("content"));
                        TencentRequest.MessageBody body2 = CustomerServiceBatchSendingServiceImpl.getTimImageElem(jsonObject.getString("imageUri"));
                        list.add(body1);
                        list.add(body2);
                    } else {
                        continue;
                    }

               /* body.setMsgType(i.getClassname());
                body.setMsgContent(i.getContent());*/

                    /*list.add(body);*/
               /* list.stream().forEach(item->{
                    item.setMsgContent(i.getContent());
                    item.setMsgType(i.getClassname());
                });*/

               /* if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")) {
                    //文本对象
                    list.forEach(item -> item.setMsgType("TIMTextElem"));
                } else if (list.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")) {
                    //图文对象
                    list.forEach(item -> item.setMsgType("TIMImageElem"));
                }*/
                    privateImportMessage.setTencentMessageBody(list);
                    try {
                        imPluginContext.getPluginService().importPrivateMessage(privateImportMessage);
                        //为已导入数据更改标识
                        imGroupService.updateStatus(info);
                    } catch (Exception e) {
                        log.error("导入私聊IM消息失败 msg:{},entity:{}", list,i, e);
                    }
                } else if (type == 3) {
                    //群组会话
                    MessageWrapper.GroupImportMessage groupImportMessage = new MessageWrapper.GroupImportMessage();
                    List<MessageWrapper.GroupImportMessageData> list = new ArrayList<>();
                    MessageWrapper.GroupImportMessageData data1 = new MessageWrapper.GroupImportMessageData();
                    List<TencentRequest.MessageBody> bodyList = new ArrayList<>();
                    //设置群组Id
                    groupImportMessage.setGroupId(i.getGroupId());
                    //设置发送人
                    String imUserId;
                    String id = i.getFromUserId();
                    //根据发送者分场景讨论
                    if (id.contains(":STUDENT")) {
                        String[] split = id.split(":");
                        String userId = split[0];
                        String clientType = split[1];
                        imUserId = getImUserId(userId, clientType);
                    } else {
                        imUserId = getImUserId(id, "TEACHER");
                    }


                    data1.setFromAccount(imUserId);
                    //设置随机数
                    data1.setRandom(new Random().nextInt());
                    //设置发送时间

                    String time = i.getDateTime();
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    try {
                        Date date = df.parse(time);
                        long dateTime = date.getTime();
                        dateTime = dateTime / (1000);
                        data1.setSendTime(dateTime);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                /*bodyList.stream().forEach(item->{
                            item.setMsgContent(i.getContent());
                            item.setMsgType(i.getClassname());
                        });*/
                    JSONObject jsonObject = JSONObject.parseObject(i.getContent());
                    if (i.getClassname().equals("RC:TxtMsg")) {
                        //文本
                        TencentRequest.MessageBody body1 = CustomerServiceBatchSendingServiceImpl.getTimTextElem(jsonObject.getString("content"));
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:ImgMsg")) {
                        //图片  GIf
                        TencentRequest.MessageBody body1 = CustomerServiceBatchSendingServiceImpl.getTimImageElem(jsonObject.getString("imageUri"));
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:GIFMsg")) {
                        //GIf
                        String remoteUrl = jsonObject.getString("remoteUrl");
                        int gifDataSize = jsonObject.getInteger("gifDataSize");
                        int width = jsonObject.getInteger("width");
                        int height = jsonObject.getInteger("height");
                        TencentRequest.MessageBody body1 = getTimGifElem(remoteUrl, gifDataSize, width, height);
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:HQVCMsg")) {
                        //语音
                        String remoteUrl = jsonObject.getString("remoteUrl");
                        int duration = jsonObject.getInteger("duration");
                        TencentRequest.MessageBody body1 = getTimSoundElem(remoteUrl, duration);
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:FileMsg")) {
                        //文件
                        String fileUrl = jsonObject.getString("fileUrl");
                        String size = jsonObject.getString("size");
                        String name = jsonObject.getString("name");

                        TencentRequest.MessageBody body1 = getTimFileElem(fileUrl, size, name);
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:SightMsg")) {
                        //视频
                        String sightUrl = jsonObject.getString("sightUrl");
                        String size = jsonObject.getString("size");
                        int duration = jsonObject.getInteger("duration");
                        String content = jsonObject.getString("content");
                        TencentRequest.MessageBody body1 = null;
                        try {
                            body1 = getTimVideoFileElem(sightUrl, size, duration, content);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:LBSMsg")) {
                        //位置
                        double latitude = jsonObject.getDouble("latitude");
                        double longitude = jsonObject.getDouble("longitude");
                        String poi = jsonObject.getString("poi");
                        TencentRequest.MessageBody body1 = getTimLocationElem(latitude, longitude, poi);
                        bodyList.add(body1);
                    } else if (i.getClassname().equals("RC:ImgTextMsg")) {
                        //图文
                        TencentRequest.MessageBody body1 = CustomerServiceBatchSendingServiceImpl.getTimTextElem(jsonObject.getString("content"));
                        TencentRequest.MessageBody body2 = CustomerServiceBatchSendingServiceImpl.getTimImageElem(jsonObject.getString("imageUri"));
                        bodyList.add(body1);
                        bodyList.add(body2);
                    } else if (i.getClassname().equals("RC:CombineMsg")) {
                        //合并转发
                        String remoteUrl = jsonObject.getString("remoteUrl");
                        int conversationType = jsonObject.getInteger("conversationType");
                        getTimRelayElem();
                    } else {
                        continue;
                    }
                /*body.setMsgContent(i.getContent());
                body.setMsgType(i.getClassname());*/

                    //文本对象
                /*if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:TxtMsg")) {
                    bodyList.forEach(item -> item.setMsgType("TIMTextElem"));
                } else if (bodyList.stream().map(TencentRequest.MessageBody::getMsgType).collect(Collectors.toList()).get(0).equals("RC:ImgMsg")) {
                    //暂未支持图文对象
                    bodyList.forEach(item -> item.setMsgType("TIMCustomElem"));
                }*/

                    data1.setTencentMessageBody(bodyList);

                    list.add(data1);
                    //导入消息列表
                    groupImportMessage.setMsgList(list);
                    try {
                        imPluginContext.getPluginService().importGroupMessage(groupImportMessage);
                        //为已导入数据更改标识
                        imGroupService.updateStatus(info);
                    } catch (Exception e) {
                        log.error("导入群组IM消息失败 msg:{},entity:{}", list,i, e);
                    }
                }
                log.info("导入消息成功：{}",i);
            } catch (Exception e) {
                log.error("导入消息失败:",e);
            }
        }
    }

    private TencentRequest.MessageBody getTimGifElem(String remoteUr,int size,int width,int height) {
        if (StringUtils.isEmpty(remoteUr) && size == 0 && width == 0 && height == 0) {
            return null;
        }

        // 腾讯云消息
        // 腾讯云消息
        ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
                .imgUrl(remoteUr)
                .suffix("GIF")
                .build();

        // 获取图片基本信息
        ImageUtil.imageToBase64(imageReq);

        // 图片格式。 JPG = 1 GIF = 2 PNG = 3 BMP = 4 其他 = 255
        // 图片类型。原图 = 1，大图 = 2，缩略图 = 3
        int imageFormat = 1;
        if ("PNG".equalsIgnoreCase(imageReq.getSuffix())) {
            imageFormat = 3;
        }
        if ("GIF".equalsIgnoreCase(imageReq.getSuffix())) {
            imageFormat = 2;
        }
        return TencentRequest.MessageBody.builder()
                .msgType("TIMImageElem")
                .msgContent(TencentRequest.ImageMessageBody.builder()
                        .uuid(imageReq.getMd5())
                        .imageFormat(imageFormat)
                        .type(1)
                        .height(height)
                        .width(width)
                        .url(remoteUr)
                        .size(imageReq.getSize()).build())
                .build();

    }

    //构建合并转发请求体
    private TencentRequest.MessageBody getTimRelayElem() {
        ImHistoryMessageWrapper.TimRelayElem timRelayElem = new ImHistoryMessageWrapper.TimRelayElem();
        //todo
        //timRelayElem.setMsgNum();

        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
        messageBody.setMsgType("TIMRelayElem");
        messageBody.setMsgContent(timRelayElem);
        return  messageBody;
    }

    //构建位置请求体
    private TencentRequest.MessageBody getTimLocationElem(double latitude, double longitude, String poi) {
        if (latitude == 0 && longitude == 0 &&  StringUtils.isEmpty(poi)) {
            return null;
        }
        ImHistoryMessageWrapper.TimLocationElem timLocationElem = new ImHistoryMessageWrapper.TimLocationElem();
        timLocationElem.setDesc(poi);
        timLocationElem.setLatitude(latitude);
        timLocationElem.setLongitude(longitude);

        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
        messageBody.setMsgType("TIMLocationElem");
        messageBody.setMsgContent(timLocationElem);
        return  messageBody;
    }

    //构建视频请求体
    public  TencentRequest.MessageBody getTimVideoFileElem(String sightUrl, String size, int duration, String content) throws IOException {
        if (StringUtils.isEmpty(sightUrl) && StringUtils.isEmpty(sightUrl) && duration == 0) {
            return null;
        }
        ByteArrayInputStream bais = null;
        String  format = "";
        //判断是否有前缀
        if (content.contains(",")){
            String[] split = content.split(",");
            String s = split[0];
            format = s.substring(s.indexOf("/")+ 1,s.indexOf(";"));
            content = split[1];
        } else {
            format = "JPG";
        }

            byte[] bytes = Base64.getDecoder().decode(content);
            //构建字节数组输入流
            bais = new ByteArrayInputStream(bytes);



        UploadReturnBean uploadReturnBean = uploadFileService.uploadFile(bais, format);
        String url = uploadReturnBean.getUrl();
        URL url2 =  new URL(url);
        BufferedImage read = ImageIO.read(url2);
        int width = read.getWidth();
        int height = read.getHeight();

        ImageUtil.ImageInfo imageReq = ImageUtil.ImageInfo.builder()
                .imgUrl(url)
                .suffix(format)
                .build();

        // 获取图片基本信息
        ImageUtil.imageToBase64(imageReq);

        ImHistoryMessageWrapper.TimVideoFileElem timVideoFileElem = new ImHistoryMessageWrapper.TimVideoFileElem();
        timVideoFileElem.setVideoUrl(sightUrl);
        timVideoFileElem.setVideoUUID(UUID.randomUUID().toString());
        timVideoFileElem.setVideoSize(Integer.valueOf(size));
        timVideoFileElem.setVideoSecond(duration);
        timVideoFileElem.setVideoFormat("mp4");
        timVideoFileElem.setVideoDownloadFlag(2);
        timVideoFileElem.setThumbUrl(url);
        timVideoFileElem.setThumbUUID(imageReq.getMd5());
        timVideoFileElem.setThumbWidth( width);
        timVideoFileElem.setThumbHeight( height);
        //timVideoFileElem.setThumbSize((imageReq.getSize().intValue()));
        timVideoFileElem.setThumbDownloadFlag(2);
        timVideoFileElem.setThumbFormat(format);

        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
        messageBody.setMsgType("TIMVideoFileElem");
        messageBody.setMsgContent(timVideoFileElem);
        return  messageBody;
    }

    //构建文件请求体
    public static TencentRequest.MessageBody getTimFileElem(String fileUrl, String size, String name) {
        if (StringUtils.isEmpty(fileUrl) && StringUtils.isEmpty(size) &&  StringUtils.isEmpty(name)) {
            return null;
        }
        ImHistoryMessageWrapper.TimFileElem timFileElem = new ImHistoryMessageWrapper.TimFileElem();
        timFileElem.setUrl(fileUrl);
        timFileElem.setUUID(UUID.randomUUID().toString());
        timFileElem.setFileName(name);
        timFileElem.setFileSize(Integer.valueOf(size));
        timFileElem.setDownload_Flag(2);

        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
        messageBody.setMsgType("TIMFileElem");
        messageBody.setMsgContent(timFileElem);
        return  messageBody;
    }

    //构造语音请求体
    public static TencentRequest.MessageBody getTimSoundElem(String remoteUrl,int duration) {
        if (StringUtils.isEmpty(remoteUrl) && duration == 0) {
            return null;
        }

        ImHistoryMessageWrapper.TimSoundElem timSoundElem = new ImHistoryMessageWrapper.TimSoundElem();
        timSoundElem.setUrl(remoteUrl);
        timSoundElem.setUUID(UUID.randomUUID().toString());
        timSoundElem.setSecond(duration);
        timSoundElem.setDownload_Flag(2);

        TencentRequest.MessageBody messageBody = new TencentRequest.MessageBody();
        messageBody.setMsgType("TIMSoundElem");
        messageBody.setMsgContent(timSoundElem);
        return  messageBody;
    }


    private History getHistory() {
        RongCloud rongCloud = RongCloud.getInstance(appKey, appSecret);
        History history = new History(appKey, appSecret);
        history.setRongCloud(rongCloud);
        return history;
    }


    /**
     * 群迁移
     */
    @Override
    public void groupTransfer() {
        int page = 1;
        int size = 100;
        List<ImGroup> imGroups = this.lambdaQuery().orderByDesc(ImGroup::getCreateTime)
                .last("limit " + ((page - 1) * size) + "," + size).list();
        while (!imGroups.isEmpty()) {
            groupTransfer(imGroups);

            page++;
            imGroups = this.lambdaQuery().orderByDesc(ImGroup::getCreateTime)
                    .last("limit " + ((page - 1) * size) + "," + size).list();
        }
    }

    @Override
    public int queryCount() {
        return getDao().queryCount();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void joinImGroup(String roomId, BasicUserInfo userInfo, String serverProvider, List<Long> studentIds) throws Exception {

        String joinImGroupKey = "joinImGroup:" + roomId;
        // VIP课或网络课，IM群聊已创建标识
        Boolean exists = redisTemplate.opsForValue().setIfAbsent(joinImGroupKey, roomId, 1L, TimeUnit.DAYS);
        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serverProvider);
        if (Optional.ofNullable(exists).orElse(false)) {
            // 群组老师信息
            List<ImGroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList(ImGroupMemberWrapper.ImGroupMember
                    .builder()
                    .userId(userInfo.getUserId())
                    .imUserId(imGroupService.getImUserId(userInfo.getUserId(), ClientEnum.TEACHER))
                    .imUserIdFormat(false)
                    .build());

            for (Long studentId : studentIds) {
                groupMembers.add(ImGroupMemberWrapper.ImGroupMember
                        .builder()
                        .userId(studentId)
                        .imUserId(imGroupService.getImUserId(studentId, ClientEnum.STUDENT))
                        .imUserIdFormat(false)
                        .build());
            }
            try {
                // 创建群组
                log.info("createImGroup: roomId = {}, userId = {}", roomId, userInfo.getUserId());
                if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(pluginService.pluginName())) {

                    // 群组帐号注册
                    try {
                        pluginService.register(userInfo.getImUserId(), userInfo.getRealName(), userInfo.getAvatar());
                    } catch (Exception e) {
                        log.error("直播房间群主注册失败: userId={}",userInfo.getUserId(), e);
                    }

                    // 生成群组
                    pluginService.chatRoomCreate(roomId, roomId, userInfo.getImUserId());

                    // 加入群组成员
//                    log.info("joinImGroup: roomId = {}, serviceProvider={}, userIds = {}", roomId,serverProvider, groupMembers);
//                    pluginService.chatRoomGroupJoin(roomId, roomId, groupMembers);
                } else {
                    String[] integers = groupMembers.stream().map(e->e.getImUserId()).collect(Collectors.toList()).toArray(new String[]{});
                    imHelper.joinGroup(integers, roomId, roomId);
                }

            } catch (Exception e) {

                redisTemplate.delete(joinImGroupKey);
                // 异常抛出，删除缓存标识
                throw e;
            }

        }
    }

    /**
     * 更新已修改数据的状态
     * @param info
     */
    @Override
    public void updateStatus(List<ImHistoryMessage> info) {
        getDao().updateStatus(info);
    }

    @Override
    public RTCRoomPluginService getRTCRoomPluginService(String serviceProvider) {
        return rtcRoomPluginContext.getPluginService(serviceProvider);
    }

    @Override
    public Boolean updateImGroup(ImGroup imGroup) {

        this.updateById(imGroup);
        try {
            imGroupCoreService.modifyGroupInfo(imGroup.getId(),imGroup.getName(),imGroup.getImg());
        } catch (Exception e) {
            log.error("修改群组信息失败",e);
        }
        return true;
    }

    @Override
    public void clearImportIm(List<ImHistoryMessage> info) {

        for (int j = 0; j < info.size(); j++) {
            ImHistoryMessage i = info.get(j);//判断消息类型
            log.info("消息删除：{}", j);
            Integer type = i.getTargetType();
            try {
                if (type == 1) {
                    //单聊会话
                    MessageWrapper.PrivateImportMessage privateImportMessage = new MessageWrapper.PrivateImportMessage();
                    //2：表示历史消息导入，消息不计入未读计数，且消息不会推送到终端
                    privateImportMessage.setSyncFromOldSystem(2);
                    //设置发送人
                    //根据发送者分场景讨论
                    String id = i.getFromUserId();
                    String imUserId;
                    if (id.contains(":STUDENT")) {
                        String[] split = id.split(":");
                        String userId = split[0];
                        String clientType = split[1];
                        imUserId = getImUserId(userId, clientType);
                    } else {
                        imUserId = getImUserId(id, "TEACHER");
                    }

                    String targetId = i.getTargetId();
                    try {
                        imGroupCoreService.deletePrivateRecentContact(imUserId,targetId);
                    } catch (Exception e) {
                        log.error("删除私聊最近联系人失败",e);
                    }
                }
                log.info("删除消息成功：{}", i);
            } catch (Exception e) {
                log.error("删除消息失败:{}",i, e);
            }
        }
    }

    @Override
    public void groupAvatarUpdate() {
        int page = 1;
        int size = 100;
        List<ImGroup> imGroups = this.lambdaQuery().orderByDesc(ImGroup::getCreateTime)
            .last("limit " + ((page - 1) * size) + "," + size).list();
        while (!imGroups.isEmpty()) {
            groupAvatarUpdate(imGroups);

            page++;
            imGroups = this.lambdaQuery().orderByDesc(ImGroup::getCreateTime)
                .last("limit " + ((page - 1) * size) + "," + size).list();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean muteAll(ImGroupWrapper.Mute mute) {
        String groupId = mute.getGroupId();
        Boolean muteAll = mute.getMuteAll();
        ImGroup imGroup = imGroupService.lambdaQuery().eq(ImGroup::getId, groupId).last("LIMIT 1").one();
        if (Objects.isNull(imGroup)) {
            throw new BizException("群组不存在");
        }
        ImGroupWrapper.ImGroupConfigJson from = ImGroupWrapper.ImGroupConfigJson.builder().mute(muteAll).build();
        imGroup.setConfigJson(JSON.toJSONString(from));
        imGroupService.updateById(imGroup);

        // 调用IM接口
        try {
            if (Boolean.TRUE.equals(muteAll)) {
                imPluginContext.getPluginService().groupBanCreate(groupId);
            } else {
                imPluginContext.getPluginService().groupBanRemove(groupId);
            }
        } catch (Exception e) {
            log.error("群组禁言状态修改失败", e);
            throw new BizException("群组禁言状态修改失败");
        }
        return true;
    }

    private void groupAvatarUpdate(List<ImGroup> records) {

        for (ImGroup imGroup : records) {

            try {
                imGroupCoreService.modifyGroupInfo(imGroup.getId(), imGroup.getName(), imGroup.getImg());
            } catch (Exception e) {
                log.error("群头像更新失败：" + JSON.toJSONString(imGroup), e);
            }
        }
    }


    private void groupTransfer(List<ImGroup> records) {
        String fansIcon = sysConfigService.findConfigValue(SysConfigConstant.ICON_FANS_GROUP_DEFAULT);
        String courseIcon = sysConfigService.findConfigValue(SysConfigConstant.ICON_COURSE_GROUP_DEFAULT);
        String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.DEFAULT_HEARD);
//        for (ImGroup imGroup : records) {
//
//            log.info("群销毁开始：{}", imGroup.getId());
//            // 先删除群组
//            try {
//                // 解散群
//                imPluginContext.getPluginService().groupDismiss(imGroup.getId(), new ArrayList<>());
//            } catch (Exception e) {
//                log.error(String.format("群迁移删除群聊失败：%s", e.getMessage()), e);
//            }
//        }
        for (ImGroup imGroup : records) {

            log.info("群迁移开始：{}", imGroup.getId());
//            // 先删除群组
//            try {
//                // 解散群
//                imPluginContext.getPluginService().groupDismiss(imGroup.getId(), new ArrayList<>());
//            } catch (Exception e) {
//                log.error(String.format("群迁移删除群聊失败：%s", e.getMessage()),e);
//            }

            List<ImGroupMember> memberList = imGroupMemberService.lambdaQuery()
                    .eq(ImGroupMember::getGroupId, imGroup.getId())
                    .le(ImGroupMember::getCreateTime,imGroup.getCreateTime())
                    .list();
            if (CollectionUtils.isEmpty(memberList)) {
                continue;
            }
            log.info("群数据补录，群ID：{}，补录人数：{}", imGroup.getId(), memberList.size());
            ImGroupMember admin = memberList.stream().filter(ImGroupMember::getIsAdmin).findFirst().orElse(null);
            if (admin == null) {
                log.info("群主不存在，groupId:{}",imGroup.getId());
                continue;
            }
            try {
                MessageWrapper.ImportGroup importGroup = new MessageWrapper.ImportGroup();
                importGroup.setOwnerAccount(getImUserId(admin.getUserId().toString(), "TEACHER"));
                importGroup.setType("Public");
                importGroup.setGroupId(imGroup.getId());
                importGroup.setName(imGroup.getName());
                importGroup.setIntroduction(imGroup.getIntroduce());
                importGroup.setNotification(imGroup.getMemo());
                importGroup.setFaceUrl(imGroup.getImg());
                if (StringUtils.isEmpty(imGroup.getImg())) {
                    if (imGroup.getType().equals(ImGroupType.COURSE)) {
                        importGroup.setFaceUrl(courseIcon);
                    } else {
                        importGroup.setFaceUrl(fansIcon);
                    }
                }
                importGroup.setApplyJoinOption(Boolean.TRUE.equals(imGroup.getAutoPassFlag()) ? "FreeAccess" :
                        "NeedPermission");
                importGroup.setCreateTime(imGroup.getCreateTime().getTime() / 1000);

                register(admin.getUserId(), imGroup.getId(), admin.getAvatar(), true, ClientEnum.TEACHER);
//                imPluginContext.getPluginService().importGroup(importGroup);

                List<ImGroupMember> groupMembers = memberList.stream()
                        .filter(next -> !next.getIsAdmin()).collect(Collectors.toList());
                if (groupMembers.isEmpty()) {
                    continue;
                }
                for (ImGroupMember member : groupMembers) {
                    String avatar = member.getAvatar();
                    if (StringUtils.isEmpty(avatar)) {
                        avatar = defaultHeard;
                    }
                    register(member.getUserId(), imGroup.getId(), avatar, false,
                            ImGroupMemberRoleType.STUDENT.equals(member.getRoleType()) ? ClientEnum.STUDENT :
                                    ClientEnum.TEACHER);
                }
                MessageWrapper.ImportGroupMember importGroupMember = new MessageWrapper.ImportGroupMember();
                importGroupMember.setGroupId(imGroup.getId());
                Date date = new DateTime(imGroup.getCreateTime()).plusSeconds(3).toDate();
                List<MessageWrapper.ImportGroupMemberData> members =
                        groupMembers.stream().map(next -> {
                            MessageWrapper.ImportGroupMemberData data = new MessageWrapper.ImportGroupMemberData();
                            data.setMemberAccount(getImUserId(next.getUserId().toString(),
                                    ImGroupMemberRoleType.STUDENT.equals(next.getRoleType()) ?
                                            ClientEnum.STUDENT.name() :
                                            ClientEnum.TEACHER.name()));
                            data.setJoinTime(date.getTime() / 1000);
                            data.setUnreadMsgNum(0);
                            return data;
                        }).collect(Collectors.toList());
                List<List<MessageWrapper.ImportGroupMemberData>> partition = Lists.partition(members, 6);
                for (List<MessageWrapper.ImportGroupMemberData> importGroupMemberData : partition) {
                    importGroupMember.setMemberList(importGroupMemberData);
                    imPluginContext.getPluginService().importGroupMember(importGroupMember);
                }
            } catch (Exception e) {
                log.error(String.format("群迁移加入群聊失败：%s", e.getMessage()));
            }
            log.info("群迁移成功：{}", imGroup.getId());
        }
    }

    private void register(Long userId, String imGroupId, String avatar, Boolean admin, ClientEnum clientType) {
        SysUser user = sysUserService.getByUserId(userId);

        // 群组默认头象
        List<GroupMemberWrapper.ImGroupMember> groupMembers = Lists.newArrayList();
        //记录群成员
        GroupMemberWrapper.ImGroupMember groupMember = GroupMemberWrapper.ImGroupMember
                .builder()
                .id(IdWorker.getId())
                .groupId(imGroupId)
                .userId(userId)
                .clientType(clientType.getCode())
                .avatar(avatar)
                .nickname(user.getUsername())
                .isAdmin(admin)
                .imUserId(getImUserId(userId.toString(), clientType.getCode()))
                .roleType(clientType.getCode())
                .build();
        groupMembers.add(groupMember);

        // 自动激活学生IM帐号
        registerUser(groupMembers);
    }


    @Override
    public void importUser() {
        int page = 1;
        int rows = 200;
        List<String[]> teachers = getTeachers(page, rows);
        while (!teachers.isEmpty()) {
            register(teachers);
            page++;
            teachers = getTeachers(page, rows);
        }
        page = 1;


        List<String[]> student = getStudent(page, rows);
        while (!student.isEmpty()) {
            register(student);
            page++;
            student = getStudent(page, rows);
        }
    }

    private void register(List<String[]> users) {
        for (String[] user : users) {
            try {
                register(user[0], ClientEnum.valueOf(user[1]), user[2], user[3]);
            } catch (Exception e) {
                log.error("注册失败：" + JSON.toJSONString(user) + e.getMessage());
            }
        }
    }

    private  List<String[]> getStudent(int page,int rows) {
        String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.DEFAULT_HEARD);
        StudentSearch studentQuery = new StudentSearch();
        studentQuery.setPage(page);
        studentQuery.setRows(rows);
        IPage<StudentVo> studentIPage = studentService.selectPage(PageUtil.getPage(studentQuery), studentQuery);
        return studentIPage.getRecords().stream().map(next -> {
            String[] strings = new String[4];
            strings[0] = next.getUserId().toString();
            strings[1] = ClientEnum.STUDENT.name();
            strings[2] = next.getUsername();
            String avatar = next.getAvatar();
            strings[3] = avatar;
            if (StringUtils.isEmpty(avatar)) {
                strings[3] = defaultHeard;
            }
            return strings;
        }).collect(Collectors.toList());
    }

    private List<String[]> getTeachers(int page, int rows) {
        String defaultHeard = sysConfigService.findConfigValue(SysConfigConstant.DEFAULT_HEARD);
        TeacherSearch query = new TeacherSearch();
        query.setPage(page);
        query.setRows(rows);
        IPage<TeacherVo> teacherIPage = teacherService.selectPage(PageUtil.getPage(query), query);
        List<TeacherVo> records = teacherIPage.getRecords();
        return records.stream().map(next -> {
            String[] strings = new String[4];
            strings[0] = next.getUserId().toString();
            strings[1] = ClientEnum.TEACHER.name();
            strings[2] = next.getRealName();
            String avatar = next.getAvatar();
            strings[3] = avatar;
            if (StringUtils.isEmpty(avatar)) {
                strings[3] = defaultHeard;
            }
            return strings;
        }).collect(Collectors.toList());
    }
}

