package com.wecloud.im.service.impl;

import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.geekidea.springbootplus.framework.common.enums.BaseEnum;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.geekidea.springbootplus.framework.common.service.impl.BaseServiceImpl;
import io.geekidea.springbootplus.framework.core.pagination.PageInfo;
import io.geekidea.springbootplus.framework.core.pagination.Paging;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chanjx.utils.StringUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.wecloud.im.chatroom.cache.ChatRoomCacheManager;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.mapper.ImConversationMapper;
import com.wecloud.im.param.ChatRoomMemberPageParam;
import com.wecloud.im.param.DisbandConversationParam;
import com.wecloud.im.param.ExitChatRoomParam;
import com.wecloud.im.param.GroupChatSettingParam;
import com.wecloud.im.param.ImClientSimpleDto;
import com.wecloud.im.param.ImConversationPageParam;
import com.wecloud.im.param.ImConversationQueryParam;
import com.wecloud.im.param.ImConversationQueryVo;
import com.wecloud.im.param.IntoChatRoomParam;
import com.wecloud.im.param.ListConversationMembersParam;
import com.wecloud.im.param.ListConversationParam;
import com.wecloud.im.param.MutedGroupMemberParam;
import com.wecloud.im.param.MutedGroupParam;
import com.wecloud.im.param.SetAdminsParam;
import com.wecloud.im.param.TransferOwnerParam;
import com.wecloud.im.param.add.ImClientLeaveConversation;
import com.wecloud.im.param.add.ImClientToConversation;
import com.wecloud.im.param.add.ImConversationAttrUpdate;
import com.wecloud.im.param.add.ImConversationCreate;
import com.wecloud.im.param.add.ImConversationDisplayUpdate;
import com.wecloud.im.param.add.ImConversationNameUpdate;
import com.wecloud.im.param.add.ServerImConversationCreate;
import com.wecloud.im.sdk.enums.ChatTypeEnum;
import com.wecloud.im.sdk.enums.GroupChatSettingTypeEnum;
import com.wecloud.im.sdk.enums.GroupRoleEnum;
import com.wecloud.im.sdk.enums.MutedEnum;
import com.wecloud.im.service.ContextService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationMembersService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.vo.ChatRoomMemberVo;
import com.wecloud.im.vo.ConversationMemberVo;
import com.wecloud.im.vo.ConversationVo;
import com.wecloud.im.vo.ImConversationCreateVo;
import com.wecloud.im.vo.OfflineMsgDto;
import com.wecloud.im.ws.enums.MsgTypeEnum;
import com.wecloud.im.ws.enums.WsResponseCmdEnum;
import com.wecloud.im.ws.model.WsResponse;
import com.wecloud.im.ws.sender.ChannelSender;
import com.wecloud.im.ws.utils.RedisUtils;
import com.wecloud.utils.JsonUtils;
import com.wecloud.utils.SnowflakeUtil;

import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_ADD_FRIEND;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_ADD_FRIEND_CANCEL;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_SEND_LINK;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_SEND_LINK_CANCEL;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_SEND_PIC;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_SEND_PIC_CANCEL;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_SEND_RED_PACKETS;
import static com.wecloud.im.ws.enums.MsgTypeEnum.CONVERSATION_FORBID_SEND_RED_PACKETS_CANCEL;

/**
 * 会话表 服务实现类
 *
 * @author wei
 * @since 2021-05-07
 */
@Slf4j
@Service
@CacheConfig(cacheNames = "convstn")
public class ImConversationServiceImpl extends BaseServiceImpl<ImConversationMapper, ImConversation> implements ImConversationService {

    @Autowired
    private ChannelSender channelSender;

    @Autowired
    private ImConversationMapper imConversationMapper;

    @Autowired
    private ImConversationMembersService imConversationMembersService;

    @Autowired
    private ImConversationService imConversationService;

    @Autowired
    private ImClientService imClientService;

    @Autowired
    private ImMessageService imMessageService;

    @Autowired
    private ContextService contextService;

    @Autowired
    private ChatRoomCacheManager chatRoomCacheManager;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveImConversation(ImConversation imConversation) {
        return super.save(imConversation);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ImConversationCreateVo createImConversation(ImConversationCreate imConversationCreate) {
        if (BaseEnum.valueOf(ChatTypeEnum.class, imConversationCreate.getChatType()) == null) {
            log.info("会话类型不存在");
            throw new BusinessException(ApiCode.PARAMETER_EXCEPTION);
        }
        ImClient createClient = contextService.getImClientIfNotNullOrThrow();
        if (ChatTypeEnum.CHAT_ROOM.getCode().equals(imConversationCreate.getChatType())) {
            // 聊天室
            return this.createChatRoom(imConversationCreate, createClient);
        }
        if (CollectionUtils.isEmpty(imConversationCreate.getClientIds())) {
            log.info("未找到群成员信息");
            throw new BusinessException(ApiCode.PARAMETER_EXCEPTION);
        }
        // 成员不存在,不能创建会话
        for (String clientId : imConversationCreate.getClientIds()) {
            ImClient imClient = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .select(ImClient::getId)
                    .eq(ImClient::getFkAppid, createClient.getFkAppid())
                    .eq(ImClient::getClientId, clientId));
            if (imClient == null) {
                log.info("成员不存在,不能创建会话 clientId:{}", clientId);
                throw new BusinessException(ApiCode.CLIENT_NOT_FOUNT);
            }
        }

        //  根据appKey查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());

        // 该应用 是否允许创建重复单聊类型会话 0不允许 1允许
        if (imApplication.getRepeatSessionStatus() != null && imApplication.getRepeatSessionStatus() == 0) {
            // 判断是否已经存在单聊类型会话
            // size() == 1 为单聊不允许重复创建 两个用户如果已经创建过会话,不能重复创建会话
            if (imConversationCreate.getClientIds().size() == 1) {
                ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, createClient.getFkAppid())
                        .eq(ImClient::getClientId, imConversationCreate.getClientIds().get(0)));

                // 如果存在重复单聊类型会话，则不会为空
                ImConversation repetitionConversationInfo = imConversationMapper.getRepetitionConversationSingle(createClient.getId(), client2.getId());
                if (repetitionConversationInfo != null) {
                    log.info("存在重复的单聊会话，返回已存在的单聊类型会话id: {}", repetitionConversationInfo.getId());
                    // 返回已存在的单聊类型会话id
                    ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
                    imConversationCreateVo.setId(repetitionConversationInfo.getId());
                    return imConversationCreateVo;
                }
            }
        } else {
            //创建重复一对一会话时对比扩展字段  1是
            if (imApplication.getContrastExtendedFieldStatus() == 1) {

                // 被邀请client
                ImClient inviteClient = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, createClient.getFkAppid())
                        .eq(ImClient::getClientId, imConversationCreate.getClientIds().get(0)));
                log.info("RequestAttributes:" + imConversationCreate.getAttributes());


                Long repetitionConversation = getRepetitionConversationAttributes(createClient.getId(), inviteClient.getId(), imConversationCreate.getAttributes());

                // 存在重复会话
                if (repetitionConversation != null) {
                    log.info("出现Attributes重复");
                    ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
                    imConversationCreateVo.setId(repetitionConversation);
                    // 为重复
                    return imConversationCreateVo;
                }
            }
        }

        // 会话id
        Long imConversationId = SnowflakeUtil.getId();

        // 创建者
        Long creator = createClient.getId();

        // 创建会话
        ImConversation imConversation = new ImConversation();
        imConversation.setId(imConversationId);
        imConversation.setCreateTime(new Date());
        imConversation.setLastMessage(null);
        imConversation.setFkAppid(createClient.getFkAppid());
        imConversation.setCreator(creator);
        imConversation.setMemberCount(imConversationCreate.getClientIds().size() + 1);
        imConversation.setChatType(imConversationCreate.getChatType());
        imConversation.setName(imConversationCreate.getName());
        imConversation.setSystemFlag(false);
        // 拓展数据
        String attributesStr = JsonUtils.encodeJson(imConversationCreate.getAttributes());

        imConversation.setAttributes(attributesStr);
        imConversationService.save(imConversation);

        // 将创建者自己添加到会话
        Long imConversationMembersId = SnowflakeUtil.getId();
        ImConversationMembers imConversationMembers = new ImConversationMembers();
        imConversationMembers.setId(imConversationMembersId);
        imConversationMembers.setCreateTime(new Date());
        imConversationMembers.setUpdateTime(new Date());
        imConversationMembers.setFkAppid(createClient.getFkAppid());
        imConversationMembers.setFkConversationId(imConversationId);
        imConversationMembers.setFkClientId(creator);
        imConversationMembers.setClientId(createClient.getClientId());
        imConversationMembers.setRole(GroupRoleEnum.OWNER.getCode());
        imConversationMembersService.save(imConversationMembers);

        // 将他人添加到会话
        for (String id : imConversationCreate.getClientIds()) {
            ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, createClient.getFkAppid())
                    .eq(ImClient::getClientId, id));
            ImConversationMembers imConversationMembers2 = new ImConversationMembers();
            imConversationMembers2.setId(SnowflakeUtil.getId());
            imConversationMembers2.setCreateTime(new Date());
            imConversationMembers2.setUpdateTime(new Date());
            imConversationMembers2.setFkAppid(createClient.getFkAppid());
            imConversationMembers2.setFkConversationId(imConversationId);
            imConversationMembers2.setFkClientId(client2.getId());
            imConversationMembers2.setClientId(client2.getClientId());
            imConversationMembers2.setRole(GroupRoleEnum.NORMAL.getCode());
            imConversationMembersService.save(imConversationMembers2);
            if (imConversationCreate.getClientIds().size() > 1) {
                // 给被拉入群的成员下发事件消息 -- 单聊则不下发
                ImMessage imMessage = new ImMessage();
                Map<String, Object> content = Maps.newHashMap();
                content.put("operator", createClient.getClientId()); //操作的client ID
                content.put("passivityOperator", client2.getClientId()); //被操作的client ID
                imMessage.setContent(JsonUtils.encodeJson(content));

                //  保存消息至消息表
                imMessage.setId(SnowflakeUtil.getId());
                imMessage.setMsgType(MsgTypeEnum.CLIENT_JOIN_NEW_CONVERSATION.getUriCode());
                imMessage.setCreateTime(new Date());
                imMessage.setFkAppid(imApplication.getId());
                imMessage.setSender(createClient.getId());
                imMessage.setWithdraw(false);
                imMessage.setEvent(true);
                imMessage.setSystemFlag(false);
                imMessage.setSendStatus(2);
                imMessage.setFkConversationId(imConversation.getId());
                imMessageService.save(imMessage);
                // 发送消息
                sendEventMsgToMember(imConversation.getId(), imApplication.getId(), createClient.getClientId(),
                        client2.getId(), content, imMessage);
            }
        }
        ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
        imConversationCreateVo.setId(imConversationId);

        return imConversationCreateVo;
    }

    @Override
    public ImConversation serverCreateImConversation(ServerImConversationCreate imConversationCreate) {
        if (ChatTypeEnum.CHAT_ROOM.equals(imConversationCreate.getChatType())) {
            // 聊天室
            throw new BusinessException("不允许创建聊天室");
        }
        ImApplication imApplication = imConversationCreate.getApplication();
        ImClient creator = imConversationCreate.getCreator();
        Long appId = creator.getFkAppid();

        if (CollectionUtils.isEmpty(imConversationCreate.getMembers())) {
            log.info("未找到群成员信息");
            throw new BusinessException(ApiCode.PARAMETER_EXCEPTION);
        }

        // 该应用 是否允许创建重复单聊类型会话 0不允许 1允许
        if (imApplication.getRepeatSessionStatus() != null && imApplication.getRepeatSessionStatus() == 0) {
            // 判断是否已经存在单聊类型会话
            // size() == 1 为单聊不允许重复创建 两个用户如果已经创建过会话,不能重复创建会话
            if (imConversationCreate.getMembers().size() == 1) {
                ImClient member = imConversationCreate.getMembers().get(0);
                // 如果存在重复单聊类型会话，则不会为空
                ImConversation repetitionConversationInfo =
                        imConversationMapper.getRepetitionConversationSingle(creator.getId(), member.getId());
                if (repetitionConversationInfo != null) {
                    log.info("存在重复的单聊会话，返回已存在的单聊类型会话id: {}", repetitionConversationInfo.getId());
                    // 返回已存在的会话
                    return repetitionConversationInfo;
                }
            }
        } else {
            //创建重复一对一会话时对比扩展字段  1是
            if (imApplication.getContrastExtendedFieldStatus() == 1) {

                // 被邀请client
                ImClient member = imConversationCreate.getMembers().get(0);
                log.info("RequestAttributes:" + imConversationCreate.getAttributes());


                Long repetitionConversation = getRepetitionConversationAttributes(creator.getId(), member.getId(),
                        imConversationCreate.getAttributes());

                // 存在重复会话
                if (repetitionConversation != null) {
                    log.info("出现Attributes重复");
                    // 为重复
                    return getById(repetitionConversation);
                }
            }
        }

        // 会话id
        Long imConversationId = SnowflakeUtil.getId();

        // 创建者
        Long creatorImClientId = creator.getId();

        // 创建会话
        ImConversation imConversation = new ImConversation();
        imConversation.setId(imConversationId);
        imConversation.setCreateTime(new Date());
        imConversation.setLastMessage(null);
        imConversation.setFkAppid(appId);
        imConversation.setCreator(creatorImClientId);
        imConversation.setMemberCount(imConversationCreate.getMembers().size() + 1);
        imConversation.setChatType(imConversationCreate.getChatType().getCode());
        imConversation.setName(imConversationCreate.getName());
        imConversation.setSystemFlag(false);
        // 拓展数据
        String attributesStr = JsonUtils.encodeJson(imConversationCreate.getAttributes());

        imConversation.setAttributes(attributesStr);
        imConversationService.save(imConversation);

        // 将创建者自己添加到会话
        Long imConversationMembersId = SnowflakeUtil.getId();
        ImConversationMembers conversationCreator = new ImConversationMembers();
        conversationCreator.setId(imConversationMembersId);
        conversationCreator.setCreateTime(new Date());
        conversationCreator.setUpdateTime(new Date());
        conversationCreator.setFkAppid(appId);
        conversationCreator.setFkConversationId(imConversationId);
        conversationCreator.setFkClientId(creatorImClientId);
        conversationCreator.setClientId(creator.getClientId());
        conversationCreator.setRole(GroupRoleEnum.OWNER.getCode());
        imConversationMembersService.save(conversationCreator);

        // 将他人添加到会话
        for (ImClient member : imConversationCreate.getMembers()) {
            ImConversationMembers imConversationMember = new ImConversationMembers();
            imConversationMember.setId(SnowflakeUtil.getId());
            imConversationMember.setCreateTime(new Date());
            imConversationMember.setUpdateTime(new Date());
            imConversationMember.setFkAppid(appId);
            imConversationMember.setFkConversationId(imConversationId);
            imConversationMember.setFkClientId(member.getId());
            imConversationMember.setClientId(member.getClientId());
            imConversationMember.setRole(GroupRoleEnum.NORMAL.getCode());
            imConversationMembersService.save(imConversationMember);
            if (imConversationCreate.getMembers().size() > 1) {
                // 给被拉入群的成员下发事件消息 -- 单聊则不下发
                ImMessage imMessage = new ImMessage();
                Map<String, Object> content = Maps.newHashMap();
                content.put("operator", creator.getClientId()); //操作的client ID
                content.put("passivityOperator", member.getClientId()); //被操作的client ID
                imMessage.setContent(JsonUtils.encodeJson(content));

                //  保存消息至消息表
                imMessage.setId(SnowflakeUtil.getId());
                imMessage.setMsgType(MsgTypeEnum.CLIENT_JOIN_NEW_CONVERSATION.getUriCode());
                imMessage.setCreateTime(new Date());
                imMessage.setFkAppid(imApplication.getId());
                imMessage.setSender(creator.getId());
                imMessage.setWithdraw(false);
                imMessage.setEvent(true);
                imMessage.setSystemFlag(false);
                imMessage.setSendStatus(2);
                imMessage.setFkConversationId(imConversation.getId());
                imMessageService.save(imMessage);
                // 发送消息
                sendEventMsgToMember(imConversation.getId(), imApplication.getId(), creator.getClientId(),
                        member.getId(), content, imMessage);
            }
        }
        ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
        imConversationCreateVo.setId(imConversationId);

        return imConversation;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addClientToConversation(ImClientToConversation imClientToConversation) {

        // 获取当前client
        ImClient createClient = contextService.getImClientIfNotNullOrThrow();
        //  根据appId查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());

        ImClient imClientSender = imClientService.getCurrentClient();

        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, imApplication.getId())

                        .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                        .ne(ImConversationMembers::getFkClientId, imClientSender.getId())
        );
        if (membersList.isEmpty()) {
            log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
            throw new BusinessException("没有成员");
        }

        int needAddCount = 0;

        // 将他人添加到会话
        for (String id : imClientToConversation.getClientIds()) {
            ImClient clientToConversation = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, imApplication.getId())
                    .eq(ImClient::getClientId, id));
            if (clientToConversation == null) {
                throw new BusinessException(ApiCode.CLIENT_NOT_FOUNT);
            }
            //   判断用户是否已经在该会话
            ImConversationMembers members = imConversationMembersService.getOne(new QueryWrapper<ImConversationMembers>().lambda()
                    .eq(ImConversationMembers::getFkAppid, imApplication.getId())
                    .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                    .eq(ImConversationMembers::getFkClientId, clientToConversation.getId())
            );

            // 已经在该会话 则跳过
            if (members != null) {
                continue;
            }

            Long imConversationMembersId2 = SnowflakeUtil.getId();
            ImConversationMembers imConversationMembers2 = new ImConversationMembers();
            imConversationMembers2.setUpdateTime(new Date());
            imConversationMembers2.setId(imConversationMembersId2);
            imConversationMembers2.setCreateTime(new Date());
            imConversationMembers2.setFkAppid(imApplication.getId());
            imConversationMembers2.setFkConversationId(imClientToConversation.getConversationId());
            imConversationMembers2.setFkClientId(clientToConversation.getId());
            imConversationMembers2.setClientId(clientToConversation.getClientId());
            imConversationMembers2.setMuted(MutedEnum.NO.getCode());
            imConversationMembers2.setRole(GroupRoleEnum.NORMAL.getCode());
            imConversationMembersService.save(imConversationMembers2);

            needAddCount++;

            // ws邀请事件通知给群内其他人 ----------


            // 生成消息id
            long messageId = SnowflakeUtil.getId();
            ImMessage imMessage = new ImMessage();

            Map<String, Object> content = new HashMap<>();
            content.put("operator", imClientSender.getClientId()); //操作的client ID
            content.put("passivityOperator", clientToConversation.getClientId()); //被操作的client ID
            imMessage.setContent(JsonUtils.encodeJson(content));

            //  保存消息至消息表
            imMessage.setId(messageId);
            imMessage.setMsgType(MsgTypeEnum.INVITE_CLIENT_JOIN_CONVERSATION.getUriCode());
            imMessage.setCreateTime(new Date());
            imMessage.setFkAppid(imApplication.getId());
            imMessage.setSender(imClientSender.getId());
            imMessage.setWithdraw(false);
            imMessage.setEvent(true);
            imMessage.setSystemFlag(false);
            imMessage.setSendStatus(2);
            imMessage.setFkConversationId(imClientToConversation.getConversationId());
            boolean save = imMessageService.save(imMessage);

            // 遍历发送给已在群内的成员
            for (ImConversationMembers conversationMember : membersList) {
                sendEventMsgToMember(imClientToConversation.getConversationId(), imApplication.getId(), createClient.getClientId(),
                        conversationMember.getFkClientId(), content, imMessage);
            }
            sendEventMsgToMember(imClientToConversation.getConversationId(), imApplication.getId(), createClient.getClientId(),
                    clientToConversation.getId(), content, imMessage);
        }

        // 将群成员数量减
        imConversationMapper.addMemberCount(imApplication.getId(), imClientToConversation.getConversationId(), needAddCount);
        ImConversationQueryVo conversation = imConversationMapper.getImConversationById(imClientToConversation.getConversationId());
        if (conversation.getMemberCount() > 2000) {
            // 升级为万人群
            imConversationMapper.upgradeToThousandChat(imApplication.getId(), imClientToConversation.getConversationId());
        }

        return true;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delClientToConversation(ImClientToConversation imClientToConversation) throws Exception {
        // 获取当前client
        ImClient createClient = contextService.getImClientIfNotNullOrThrow();
        //  根据appId查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
        ImClient imClientSender = imClientService.getCurrentClient();
        // 判断是否为群主
        ImConversationMembers conversationMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                        .eq(ImConversationMembers::getFkClientId, imClientSender.getId())
        );
        if (conversationMember == null || !GroupRoleEnum.OWNER.getCode().equals(conversationMember.getRole())) {
            return false;
        }
        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, imApplication.getId())
                        .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                        .ne(ImConversationMembers::getFkClientId, imClientSender.getId())
        );
        if (membersList.isEmpty()) {
            log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
            throw new BusinessException("没有成员");
        }

        int needAddCount = 0;
        // 将client从会话移除
        for (String clientId : imClientToConversation.getClientIds()) {
            ImClient clientToBeRemove = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, imApplication.getId())
                    .eq(ImClient::getClientId, clientId));

            //   判断用户是否已经在该会话
            ImConversationMembers members = imConversationMembersService.getOne(new QueryWrapper<ImConversationMembers>().lambda()
                    .eq(ImConversationMembers::getFkAppid, imApplication.getId())
                    .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                    .eq(ImConversationMembers::getFkClientId, clientToBeRemove.getId())
            );
            if (members == null) {
                continue;
            }
            imConversationMembersService.deleteImConversationMembers(members.getId());

            // ws移除事件通知给群内其他人 ----------
            needAddCount--;
            // 生成消息id
            long messageId = SnowflakeUtil.getId();
            ImMessage imMessage = new ImMessage();

            Map<String, Object> content = new HashMap<>();
            content.put("operator", imClientSender.getClientId()); //操作的client ID
            content.put("passivityOperator", clientToBeRemove.getClientId()); //被操作的client ID
            imMessage.setContent(JsonUtils.encodeJson(content));
            //  保存消息至消息表
            imMessage.setId(messageId);
            imMessage.setMsgType(MsgTypeEnum.REMOVE_CLIENT_CONVERSATION.getUriCode());
            imMessage.setCreateTime(new Date());
            imMessage.setFkAppid(imApplication.getId());
            imMessage.setSender(imClientSender.getId());
            imMessage.setWithdraw(false);
            imMessage.setEvent(true);
            imMessage.setSystemFlag(false);
            imMessage.setSendStatus(2);
            imMessage.setFkConversationId(imClientToConversation.getConversationId());
            imMessageService.save(imMessage);

            membersList.removeIf(e -> e.getId().equals(members.getId()));

            Long conversationId = imClientToConversation.getConversationId();
            Long appId = imApplication.getId();
            String sender = imClientSender.getClientId();
            Integer msgType = imMessage.getMsgType();
            sendMsgToMembers(conversationId, membersList, appId, sender, content, imMessage);
        }

        // 将群成员数量减
        imConversationMapper.addMemberCount(imApplication.getId(), imClientToConversation.getConversationId(), needAddCount);
        return true;
    }

    @Override
    public void disband(DisbandConversationParam param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        // 判断是否为群主
        ImConversationMembers conversationMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .eq(ImConversationMembers::getFkClientId, currentClient.getId())
        );
        if (conversationMember == null || !GroupRoleEnum.OWNER.getCode().equals(conversationMember.getRole())) {
            throw new BusinessException("非群主无权限解散群聊");
        }
        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .ne(ImConversationMembers::getFkClientId, currentClient.getId())
        );
        if (membersList.isEmpty()) {
            throw new BusinessException("群聊成员列表为空");
        }
        // 删除所有成员
        imConversationMembersService.deleteByConversationId(param.getConversationId());
        // 保存事件消息
        ImMessage imMessage = new ImMessage();
        Map<String, Object> content = new HashMap<>();
        content.put("operator", currentClient.getClientId());
        imMessage.setContent(JsonUtils.encodeJson(content));
        //  保存消息至消息表
        imMessage.setId(SnowflakeUtil.getId());
        imMessage.setMsgType(MsgTypeEnum.CONVERSATION_DISBAND.getUriCode());
        imMessage.setCreateTime(new Date());
        imMessage.setFkAppid(currentClient.getFkAppid());
        imMessage.setSender(currentClient.getId());
        imMessage.setWithdraw(false);
        imMessage.setEvent(true);
        imMessage.setSystemFlag(false);
        imMessage.setSendStatus(2);
        imMessage.setFkConversationId(param.getConversationId());
        imMessageService.save(imMessage);

        Long conversationId = param.getConversationId();
        Long appId = currentClient.getFkAppid();
        String sender = currentClient.getClientId();

        sendMsgToMembers(conversationId, membersList, appId, sender, content, imMessage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean leaveConversation(ImClientLeaveConversation imClientToConversation) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();

        ImConversation imConversation = imConversationService.getById(imClientToConversation.getConversationId());
        if (imConversation == null) {
            throw new BusinessException("查无会话消息");
        }

        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                        .orderByAsc(ImConversationMembers::getCreateTime)
                        .ne(ImConversationMembers::getFkClientId, currentClient.getId())
        );

        if (membersList.isEmpty()) {
            log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
            throw new BusinessException("会话中查无群人员");
        }

        //   判断用户是否在该会话
        ImConversationMembers members = imConversationMembersService.getOne(new QueryWrapper<ImConversationMembers>().lambda()
                .eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
                .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                .eq(ImConversationMembers::getFkClientId, currentClient.getId())
        );

        // 将client从会话移除
        boolean b = imConversationMembersService.deleteImConversationMembers(members.getId());
        if (!b) {
            throw new BusinessException("退出群聊错误");
        }

        // 将群成员数量减1
        imConversationMapper.addMemberCount(currentClient.getFkAppid(), imClientToConversation.getConversationId(), -1);

        // ws 退出事件通知给群内其他人 ----------


        // 生成消息id
        long messageId = SnowflakeUtil.getId();
        ImMessage imMessage = new ImMessage();

        //  保存消息至消息表
        imMessage.setId(messageId);
        imMessage.setMsgType(MsgTypeEnum.LEAVE_CONVERSATION.getUriCode());
        imMessage.setCreateTime(new Date());
        imMessage.setFkAppid(currentClient.getFkAppid());
        imMessage.setSender(currentClient.getId());
        imMessage.setWithdraw(false);
        imMessage.setEvent(true);
        imMessage.setSystemFlag(false);
        imMessage.setSendStatus(2);
        imMessage.setFkConversationId(imClientToConversation.getConversationId());
        boolean save = imMessageService.save(imMessage);
        if (!save) {
            throw new BusinessException("退出群聊错误");
        }

        // 向群成员发送退出群聊事件
        Long conversationId = imClientToConversation.getConversationId();
        Long appId = currentClient.getFkAppid();
        String sender = currentClient.getClientId();
        Integer msgType = MsgTypeEnum.LEAVE_CONVERSATION.getUriCode();

        sendMsgToMembers(conversationId, membersList, appId, sender, null, imMessage);
        // 群主退出 转移给下一个人
        if (GroupRoleEnum.OWNER.getCode().equals(members.getRole())) {
            ImConversationMembers conversationMember = membersList.get(0);
            conversationMember.setRole(GroupRoleEnum.OWNER.getCode());
            // 群主转移给下一个人
            imConversationMembersService.updateById(conversationMember);
        }
        return true;
    }


    /**
     * 群主转让
     *
     * @param param
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean transferOwner(TransferOwnerParam param) {
        // 获取当前client
        ImClient createClient = contextService.getImClientIfNotNullOrThrow();
        //  根据appId查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(createClient.getFkAppid());
        ImClient imClientSender = imClientService.getCurrentClient();

        // 判断操作人是否为群主
        ImConversationMembers currentMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .eq(ImConversationMembers::getFkClientId, imClientSender.getId())
        );
        if (currentMember == null || !GroupRoleEnum.OWNER.getCode().equals(currentMember.getRole())) {
            throw new BusinessException("非群主无权操作");
        }
        // 将自己设置为普通群成员
        currentMember.setRole(GroupRoleEnum.NORMAL.getCode());
        imConversationMembersService.updateById(currentMember);
        // 将入参成员设置为群主
        ImClient transferClient = imClientService.getCacheImClient(imApplication.getId(), param.getClientId());
        ImConversationMembers transferMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .eq(ImConversationMembers::getFkClientId, transferClient.getId())
        );
        transferMember.setRole(GroupRoleEnum.OWNER.getCode());
        imConversationMembersService.updateById(transferMember);
        return true;
    }

    /**
     * 设置管理员
     *
     * @param param
     * @return
     */
    @Override
    public Boolean setAdmins(SetAdminsParam param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        // 判断操作人是否为群主
        ImConversationMembers currentMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .eq(ImConversationMembers::getFkClientId, currentClient.getId())
        );
        if (currentMember == null || !GroupRoleEnum.OWNER.getCode().equals(currentMember.getRole())) {
            throw new BusinessException("非群主无权操作");
        }
        List<ImClientSimpleDto> simpleClients = imClientService.getSimpleClients(currentClient.getFkAppid(), param.getClientIds());
        if (CollectionUtils.isEmpty(simpleClients)) {
            throw new BusinessException("未查询得到真实管理员信息");
        }
        List<Long> fkClientIds = simpleClients.stream()
                .filter(s -> !currentMember.getId().equals(s.getId()))
                .map(ImClientSimpleDto::getId).collect(Collectors.toList());
        imConversationMembersService.setAdminsForConversation(param, fkClientIds);
        return true;
    }

    /**
     * 群禁言
     *
     * @param param
     * @return
     */
    @Override
    public Boolean mutedGroup(MutedGroupParam param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        if (!imConversationService.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
                Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
            // 当前操作人不属于群主或管理人员
            throw new BusinessException("操作人既不是群主也不是群管理员，无权限操作");
        }
        ImConversation muteGroupParam = new ImConversation();
        muteGroupParam.setId(param.getConversationId());
        muteGroupParam.setUpdateTime(new Date());
        muteGroupParam.setMuted(param.getMutedType());
        imConversationMapper.updateById(muteGroupParam);
        deleteCacheImConversationById(param.getConversationId());
        // 下发事件通知 开启、取消 群禁言
        Integer msgType = MutedEnum.NO.getCode().equals(param.getMutedType()) ?
                MsgTypeEnum.CONVERSATION_MUTED_CANCEL.getUriCode()
                : MsgTypeEnum.CONVERSATION_MUTED.getUriCode();
        return true;
    }

    @Override
    public Boolean mutedGroupMember(MutedGroupMemberParam param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        if (!imConversationService.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
                Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
            // 当前操作人不属于群主或管理人员
            throw new BusinessException("操作人既不是群主也不是群管理员，无权限操作");
        }
        ListConversationMembersParam getMutedMemberParam = new ListConversationMembersParam();
        getMutedMemberParam.setConversationId(param.getConversationId());
        getMutedMemberParam.setClientIds(param.getClientIds());
        List<ConversationMemberVo> mutedMembers = imConversationMembersService.getImConversationMembersList(getMutedMemberParam);
        List<ImConversationMembers> mutedMemberList = Lists.newArrayList();
        for (ConversationMemberVo mutedMember : mutedMembers) {
            ImConversationMembers saveMutedMember = new ImConversationMembers();
            saveMutedMember.setId(mutedMember.getId());
            saveMutedMember.setUpdateTime(new Date());
            saveMutedMember.setMuted(param.getMutedType());
            mutedMemberList.add(saveMutedMember);
        }
        imConversationMembersService.updateBatchById(mutedMemberList);
        return true;
    }

    /**
     * 判断当前操作人是否为指定角色成员
     *
     * @param currentClientId
     * @param conversationId
     * @return
     */
    @Override
    public Boolean isBelongToRole(String currentClientId, Long conversationId, List<Integer> roles) {
        // 获取 群主和群管理员列表
        ListConversationMembersParam getMemberParam = new ListConversationMembersParam();
        getMemberParam.setConversationId(conversationId);
        getMemberParam.setRoles(roles);
        List<ConversationMemberVo> members = imConversationMembersService.getImConversationMembersList(getMemberParam);
        if (CollectionUtils.isEmpty(members)) {
            return false;
        }
        for (ConversationMemberVo member : members) {
            if (currentClientId.equals(member.getClientId())) {
                return true;
            }
        }
        return false;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        ImConversation imConversationById = imConversationService.getById(param.getConversationId());
        if (!this.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
                Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
            throw new BusinessException("操作人既不是群主也不是群管理员，无权限操作");
        }
        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .ne(ImConversationMembers::getFkClientId, currentClient.getId())
        );
        imConversationById.setName(param.getName());
        boolean b = imConversationService.updateById(imConversationById);
        // 删除redis中该会话的缓存
        deleteCacheImConversationById(param.getConversationId());
        if (b) {
            // 内容
            HashMap<String, String> content = Maps.newHashMap();
            content.put("name", imConversationById.getName());
            // 发送消息至成员
            ImMessage message = new ImMessage();
            message.setWithdraw(Boolean.FALSE);
            message.setEvent(Boolean.TRUE);
            message.setMsgType(MsgTypeEnum.CONVERSATION_NAME_CHANGE.getUriCode());

            sendMsgToMembers(param.getConversationId(), membersList, currentClient.getFkAppid(),
                    currentClient.getClientId(), content, message);

            return ApiResult.ok();
        } else {
            return ApiResult.fail();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateAttr(ImConversationAttrUpdate imConversationAttrUpdate) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        //  根据appId查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(currentClient.getFkAppid());

        ImConversation imConversationById = imConversationService.getById(imConversationAttrUpdate.getConversationId());
//         判断是否为群主
//        if (imConversationById == null || !imConversationById.getCreator().equals(imClientSender.getId())) {
//            return ApiResult.result(false);
//        }

        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, imApplication.getId())
                        .eq(ImConversationMembers::getFkConversationId, imConversationAttrUpdate.getConversationId())
                        .ne(ImConversationMembers::getFkClientId, currentClient.getId())
        );

        imConversationById.setAttributes(imConversationAttrUpdate.getAttributes());

        boolean b = imConversationService.updateById(imConversationById);
        // 删除redis中该会话的缓存
        deleteCacheImConversationById(imConversationAttrUpdate.getConversationId());

        if (b) {
            // ws下发拓展字段变动事件
            HashMap<String, String> content = Maps.newHashMap();
            content.put("attributes", imConversationById.getAttributes());
            // 向群成员发送拓展字段变动事件
            Long conversationId = imConversationAttrUpdate.getConversationId();
            Long appId = currentClient.getFkAppid();
            String sender = currentClient.getClientId();
            ImMessage message = new ImMessage();
            message.setWithdraw(Boolean.FALSE);
            message.setEvent(Boolean.TRUE);
            message.setMsgType(MsgTypeEnum.CONVERSATION_EXPAND_FIELD_CHANGE.getUriCode());
            sendMsgToMembers(conversationId, membersList, appId, sender, content, message);
        } else {
            throw new BusinessException("修改错误");
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateImConversation(ImConversation imConversation) {
        return super.updateById(imConversation);
    }


    /**
     * 是否单向隐藏会话","云端聊天记录不删除;假设有A和B两个用户,A删会话,B还能发; 如果B发了消息,A这边要重新把会话显示出来,并能显示之前的聊天记录"
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateDisplayConversation(ImConversationDisplayUpdate imConversationDisplayUpdate) {
        // 获取当前client
        ImClient curentClient = contextService.getImClientIfNotNullOrThrow();
        for (Long id : imConversationDisplayUpdate.getConversationIds()) {
            // 修改为删除隐藏状态
            boolean update = imConversationMembersService.update(new UpdateWrapper<ImConversationMembers>()
                    .set("display_status", imConversationDisplayUpdate.getDisplayStatus())
                    .eq("fk_client_id", curentClient.getId())
                    .eq("fk_conversation_id", id)
                    .eq("fk_appid", curentClient.getFkAppid())
            );
        }
        return true;
    }

    @Override
//    @Cacheable(key = "#p0")
    public ImConversationQueryVo getCacheImConversationById(Long id) {
        return imConversationMapper.getImConversationById(id);
    }

    @Override
    @CacheEvict(key = "#p0")
    public void deleteCacheImConversationById(Long id) {
    }

    @Override
    public Paging<ImConversationQueryVo> getImConversationPageList(ImConversationPageParam imConversationPageParam) {
        Page<ImConversationQueryVo> page = new PageInfo<>(imConversationPageParam, OrderItem.desc(getLambdaColumn(ImConversation::getCreateTime)));
        IPage<ImConversationQueryVo> iPage = imConversationMapper.getImConversationPageList(page, imConversationPageParam);
        return new Paging<ImConversationQueryVo>(iPage);
    }

    @Override
    public List<ConversationVo> getMyImConversationListAndMsgCount() {
        try {
            // 获取当前client
            ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
            // 查询用户加入的所有会话 与每个会话的未读条数 成员
            List<ConversationVo> myImConversationListAndMsgCount = imConversationMapper.getMyImConversationListAndMsgCount(currentClient.getId(), currentClient.getClientId(), null);

            // 返回的
            List<ConversationVo> myImConversationListAndMsgCountNew = new ArrayList<>();

            // 转换json格式
            for (ConversationVo myconversationlistvo : myImConversationListAndMsgCount) {
                HashMap attributess = JsonUtils.json2Map(myconversationlistvo.getAttribute());
                myconversationlistvo.setAttributes(attributess);

                // 查询会话的最后一条消息
                OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(myconversationlistvo.getId());
                myconversationlistvo.setLastMsg(lastMsg);
                if (myconversationlistvo.getBeAtCount() > 0) {
                    myconversationlistvo.setIsBeAt(Boolean.TRUE);
                }
                myImConversationListAndMsgCountNew.add(myconversationlistvo);

            }
            log.info("{} 查询加入的会话列表结果 {}", currentClient.getClientId(), JSON.toJSONString(myImConversationListAndMsgCountNew));
            return myImConversationListAndMsgCountNew;
        } catch (Exception e) {
            log.info("查询所有会话异常 ", e);
            throw new BusinessException("查询错误，稍后重试");
        }

    }

    @Override
    public ConversationVo infoImConversationAndMsgCount(ImConversationQueryParam param) {
        try {
            // 获取当前client
            ImClient client = contextService.getImClientIfNotNullOrThrow();
            // 查询用户加入的所有会话 与每个会话的未读条数 成员
            List<ConversationVo> conversationList = imConversationMapper.getMyImConversationListAndMsgCount(client.getId(), client.getClientId(), param.getId());
            if (CollectionUtils.isEmpty(conversationList)) {
                return null;
            }
            ConversationVo conversationVo = conversationList.get(0);
            HashMap attributess = JsonUtils.json2Map(conversationVo.getAttribute());
            conversationVo.setAttributes(attributess);
            // 查询会话的最后一条消息
            OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(conversationVo.getId());
            conversationVo.setLastMsg(lastMsg);
            return conversationVo;
        } catch (Exception e) {
            log.info("添加或修改会话名称异常 ", e);
            throw new BusinessException("修改会话名称错误");
        }
    }


    @Override
    public List<ImConversation> getMyImConversationList() {
        ImClient client = imClientService.getCurrentClient();
        return imConversationMapper.getMyImConversationList(client.getId());
    }

    @Override
    public Long getRepetitionConversationAttributes(Long clientId1, Long clientId2, String attributes) {
        return imConversationMapper.getRepetitionConversationAttributes(clientId1, clientId2, attributes);
    }

    @Override
    public Boolean groupChatSetting(GroupChatSettingParam param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        if (!imConversationService.isBelongToRole(currentClient.getClientId(), param.getConversationId(),
                Lists.newArrayList(GroupRoleEnum.OWNER.getCode(), GroupRoleEnum.ADMIN.getCode()))) {
            // 当前操作人不属于群主或管理人员
            throw new BusinessException("操作人既不是群主也不是群管理员，无权限操作");
        }

        // 根据类型处理
        GroupChatSettingTypeEnum typeEnum = param.getType();
        ImConversation muteGroupParam = new ImConversation();
        muteGroupParam.setId(param.getConversationId());
        muteGroupParam.setUpdateTime(new Date());
        switch (typeEnum) {
            case FORBID_ADD_FRIEND:
                muteGroupParam.setForbidAddFriend(param.getOn());
                break;
            case FORBID_SEND_RED_PACKETS:
                muteGroupParam.setForbidSendRedPackets(param.getOn());
                break;
            case FORBID_SEND_PIC:
                muteGroupParam.setForbidSendPic(param.getOn());
                break;
            case FORBID_SEND_LINK:
                muteGroupParam.setForbidSendLink(param.getOn());
                break;
            default:
                throw new BusinessException("设置类型错误");
        }
        // 更新会话
        imConversationMapper.updateById(muteGroupParam);
        deleteCacheImConversationById(param.getConversationId());
        // 发送群聊配置变化消息
        Integer msgType = getMsgType(typeEnum, param.getOn());
        sendConversationSettingChangeMsg(currentClient, param.getConversationId(), msgType);

        return true;
    }

    @Override
    public Boolean intoChatRoom(IntoChatRoomParam param) {
        // 获取当前client
        ImClient imClientSender = contextService.getImClientIfNotNullOrThrow();
        //  根据appId查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(imClientSender.getFkAppid());

        // 添加到会话成员列表中
        ImClient clientToConversation = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, imApplication.getId())
                .eq(ImClient::getClientId, param.getClientId()));
        if (clientToConversation == null) {
            throw new BusinessException(ApiCode.CLIENT_NOT_FOUNT);
        }
        // 获取房间所有成员 key是 client的主键id:platform, val是 ip
        Map<String, String> chatRoomMembers = chatRoomCacheManager.findOnlineClientsByChatRoomId(param.getChatRoomId());
        for (String key : chatRoomMembers.keySet()) {
            if (clientToConversation.getId().toString().equals(key.split(RedisUtils.SPLIT)[0])) {
                return Boolean.FALSE;
            }
        }
        chatRoomCacheManager.intoRoom(clientToConversation.getId(), param.getChatRoomId(), param.getPlatform());

        // ws邀请事件通知给群内其他人 ----------
        // 生成消息id
        long messageId = SnowflakeUtil.getId();
        ImMessage imMessage = new ImMessage();

        Map<String, Object> content = new HashMap<>();
        content.put("operator", imClientSender.getClientId()); //操作的client ID
        content.put("passivityOperator", clientToConversation.getClientId()); //被操作的client ID
        imMessage.setContent(JsonUtils.encodeJson(content));

        //  保存消息至消息表
        imMessage.setId(messageId);
        imMessage.setMsgType(MsgTypeEnum.INVITE_CLIENT_JOIN_CONVERSATION.getUriCode());
        imMessage.setCreateTime(new Date());
        imMessage.setFkAppid(imApplication.getId());
        imMessage.setSender(imClientSender.getId());
        imMessage.setWithdraw(false);
        imMessage.setEvent(true);
        imMessage.setSystemFlag(false);
        imMessage.setSendStatus(2);
        imMessage.setFkConversationId(param.getChatRoomId());

        // 遍历发送给已在群内的成员
        for (String key : chatRoomMembers.keySet()) {
            Long fkClientId = Long.valueOf(key.split(RedisUtils.SPLIT)[0]);
            sendEventMsgToMember(param.getChatRoomId(), imApplication.getId(), imClientSender.getClientId(),
                    fkClientId, content, imMessage);
        }
        imConversationMapper.addMemberCount(imApplication.getId(), param.getChatRoomId(), 1);

        return true;
    }

    @Override
    public Boolean exitChatRoom(ExitChatRoomParam param) {
        // 获取当前client
        ImClient currentClient = contextService.getImClientIfNotNullOrThrow();
        // 根据appId查询application
        ImApplication imApplication = contextService.getImApplicationIfNotNullOrThrow(currentClient.getFkAppid());
        ImConversation imConversation = imConversationService.getById(param.getChatRoomId());
        if (imConversation == null) {
            throw new BusinessException("查无会话消息");
        }
        // 获取房间所有成员 key是 client的主键id:platform, val是 ip
        Map<String, String> chatRoomMembers = chatRoomCacheManager.findOnlineClientsByChatRoomId(param.getChatRoomId());
        if (chatRoomMembers.isEmpty()) {
            throw new BusinessException("会话中查无群人员");
        }
        Boolean inRoom = Boolean.FALSE;
        for (String key : chatRoomMembers.keySet()) {
            if (currentClient.getId().toString().equals(key.split(RedisUtils.SPLIT)[0])) {
                inRoom = Boolean.TRUE;
                continue;
            }
        }
        if (!inRoom) {
            // 不在房间
            return Boolean.FALSE;
        }
        // 将群成员数量减1
        imConversationMapper.addMemberCount(currentClient.getFkAppid(), param.getChatRoomId(), -1);
        chatRoomCacheManager.exitRoom(currentClient.getId(), param.getChatRoomId(), param.getPlatform());

        // ws 退出事件通知给房间内其他人 ----------
        // 生成消息id
        long messageId = SnowflakeUtil.getId();
        ImMessage imMessage = new ImMessage();
        //  保存消息至消息表
        imMessage.setId(messageId);
        imMessage.setMsgType(MsgTypeEnum.LEAVE_CONVERSATION.getUriCode());
        imMessage.setCreateTime(new Date());
        imMessage.setFkAppid(currentClient.getFkAppid());
        imMessage.setSender(currentClient.getId());
        imMessage.setWithdraw(false);
        imMessage.setEvent(true);
        imMessage.setSystemFlag(false);
        imMessage.setSendStatus(2);
        imMessage.setFkConversationId(param.getChatRoomId());

        // 遍历发送给已在群内的成员
        for (String key : chatRoomMembers.keySet()) {
            Long fkClientId = Long.valueOf(key.split(RedisUtils.SPLIT)[0]);
            sendEventMsgToMember(param.getChatRoomId(), imApplication.getId(), currentClient.getClientId(),
                    fkClientId, null, imMessage);
        }
        return true;
    }

    @Override
    public List<ChatRoomMemberVo> listChatRoomMember(ChatRoomMemberPageParam param) {
        Map<String, String> chatRoomMembers = chatRoomCacheManager.findOnlineClientsByChatRoomId(param.getChatRoomId());
        if (chatRoomMembers.isEmpty()) {
            return Lists.newArrayList();
        }
        List<ChatRoomMemberVo> result = Lists.newArrayList();
        for (String key : chatRoomMembers.keySet()) {
            ImClient client = imClientService.getCacheImClient(Long.valueOf(key.split(RedisUtils.SPLIT)[0]));
            result.add(new ChatRoomMemberVo(param.getChatRoomId(), client.getClientId()));
        }
        return result;
    }

    @Override
    public List<ConversationVo> listConversation(ListConversationParam param) {
        if (StringUtils.isBlank(param.getConversationIds())) {
            throw new BusinessException("会话id列表不可为空");
        }
        List<Long> conversationIds = (List)JSON.parse(param.getConversationIds());
        List<ConversationVo> conversationVoList = Lists.newArrayList();
        List<ImConversation> conversations = imConversationMapper.selectList(
                new QueryWrapper<ImConversation>().lambda()
                        .eq(ImConversation::getChatType, param.getChatType())
                        .in(ImConversation::getId, conversationIds)
                        .orderByDesc(ImConversation::getId)
        );
        if (CollectionUtils.isEmpty(conversations)) {
            return conversationVoList;
        }
        for (ImConversation conversation : conversations) {
            ConversationVo conversationVo = new ConversationVo();
            BeanUtils.copyProperties(conversation, conversationVo);
            conversationVoList.add(conversationVo);
        }
        return conversationVoList;
    }

    @Override
    public List<ImConversation> getConversationBySenderAndReceivers(Long senderImClientId, Collection<Long> receiverImClientIds) {
        return baseMapper.getConversationBySenderAndReceivers(senderImClientId, receiverImClientIds);
    }

    private ImConversationCreateVo createChatRoom(ImConversationCreate imConversationCreate, ImClient createClient) {
        // 会话id
        Long chatRoomId = SnowflakeUtil.getId();

        // 创建者
        Long creator = createClient.getId();

        // 创建会话
        ImConversation imConversation = new ImConversation();
        imConversation.setId(chatRoomId);
        imConversation.setCreateTime(new Date());
        imConversation.setLastMessage(null);
        imConversation.setFkAppid(createClient.getFkAppid());
        imConversation.setCreator(creator);
        imConversation.setMemberCount(1);
        imConversation.setChatType(imConversationCreate.getChatType());
        imConversation.setName(imConversationCreate.getName());
        imConversation.setSystemFlag(false);
        imConversation.setAttributes(imConversationCreate.getAttributes());
        imConversationService.save(imConversation);

        // 将创建者自己添加到会话
        chatRoomCacheManager.intoRoom(creator, chatRoomId, imConversationCreate.getPlatform());
        ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
        imConversationCreateVo.setId(chatRoomId);

        return imConversationCreateVo;
    }

    private Integer getMsgType(GroupChatSettingTypeEnum type, Boolean on) {
        Integer msgType = null;
        switch (type) {
            case FORBID_ADD_FRIEND:
                if (on) {
                    msgType = CONVERSATION_FORBID_ADD_FRIEND.getUriCode();
                } else {
                    msgType = CONVERSATION_FORBID_ADD_FRIEND_CANCEL.getUriCode();
                }
                break;
            case FORBID_SEND_RED_PACKETS:
                if (on) {
                    msgType = CONVERSATION_FORBID_SEND_RED_PACKETS.getUriCode();
                } else {
                    msgType = CONVERSATION_FORBID_SEND_RED_PACKETS_CANCEL.getUriCode();
                }
                break;
            case FORBID_SEND_PIC:
                if (on) {
                    msgType = CONVERSATION_FORBID_SEND_PIC.getUriCode();
                } else {
                    msgType = CONVERSATION_FORBID_SEND_PIC_CANCEL.getUriCode();
                }
                break;
            case FORBID_SEND_LINK:
                if (on) {
                    msgType = CONVERSATION_FORBID_SEND_LINK.getUriCode();
                } else {
                    msgType = CONVERSATION_FORBID_SEND_LINK_CANCEL.getUriCode();
                }
                break;
            default:
                throw new BusinessException("设置类型错误");
        }

        return msgType;
    }

    /**
     * 发送会话配置变更事件
     *
     * @param currentClient  当前client信息
     * @param conversationId 会话id
     * @param msgType        消息类型
     * @Author luozh
     * @Date 2022年04月27日 01:52:54
     * @Return
     */
    private void sendConversationSettingChangeMsg(ImClient currentClient, Long conversationId, Integer msgType) {
        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
                        .eq(ImConversationMembers::getFkConversationId, conversationId)
                        .ne(ImConversationMembers::getFkClientId, currentClient.getId())
        );
        if (!membersList.isEmpty()) {
            // 保存事件消息
            ImMessage imMessage = new ImMessage();
            Map<String, Object> content = new HashMap<>();
            content.put("operator", currentClient.getClientId());
            imMessage.setContent(JsonUtils.encodeJson(content));
            //  保存消息至消息表
            imMessage.setId(SnowflakeUtil.getId());
            imMessage.setMsgType(msgType);
            imMessage.setCreateTime(new Date());
            imMessage.setFkAppid(currentClient.getFkAppid());
            imMessage.setSender(currentClient.getId());
            imMessage.setWithdraw(false);
            imMessage.setEvent(true);
            imMessage.setSystemFlag(false);
            imMessage.setSendStatus(2);
            imMessage.setFkConversationId(conversationId);
            imMessageService.save(imMessage);
            // 发送消息至群成员
            sendMsgToMembers(conversationId, membersList, currentClient.getFkAppid(), currentClient.getClientId(),
                    content, imMessage);

        }
    }

    /**
     * 发送会话事件消息至群成员列表
     *
     * @param conversationId 会话id
     * @param membersList    成员列表
     * @param appId          appId
     * @param sender         发送者
     * @param content        消息内容
     * @Author luozh
     * @Date 2022年04月27日 02:11:19
     */
    private void sendMsgToMembers(Long conversationId, List<ImConversationMembers> membersList, Long appId,
                                  String sender, Map content, ImMessage message) {
        for (ImConversationMembers member : membersList) {
            // 不关心事件是否发送成功
            try {
                // 给所有成员下发事件消息
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, appId)
                        .eq(ImClient::getId, member.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }

                sendConversationEventMsg(conversationId, sender, imClientReceiver.getId(), content, message);
            } catch (Exception e) {
                log.info("下发群会话事件失败，事件类型 {} 接收人 {}", message.getMsgType(), JSON.toJSONString(member));
            }
        }
    }

    /**
     * 发送会话事件消息至指定成员
     *
     * @param conversationId   会话id
     * @param appId            appId
     * @param sender           发送者
     * @param receiverClientId 接收者client id
     * @param message
     * @Author luozh
     * @Date 2022年04月27日 03:11:00
     */
    private void sendEventMsgToMember(Long conversationId, Long appId, String sender,
                                      Long receiverClientId, Map<String, Object> content, ImMessage message) {
        // 查询接收方
        ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, appId)
                .eq(ImClient::getId, receiverClientId));
        if (imClientReceiver == null) {
            return;
        }
        sendConversationEventMsg(conversationId, sender, receiverClientId, content, message);

    }

    /**
     * 发送会话事件消息
     *
     * @param conversationId   会话id
     * @param sender           发送者
     * @param receiverClientId 接收者client id
     * @param content          消息内容
     * @Author luozh
     * @Date 2022年04月27日 03:11:34
     */
    private void sendConversationEventMsg(Long conversationId, String sender,
                                          Long receiverClientId, Map<String, Object> content, ImMessage message) {
        // 封装响应的实体
        ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();

        imMessageOnlineSend.setMsgId(message.getId());
        imMessageOnlineSend.setCreateTime(new Date());
        imMessageOnlineSend.setType(message.getMsgType());
        imMessageOnlineSend.setSender(sender);
        imMessageOnlineSend.setContent(content);
        imMessageOnlineSend.setConversationId(conversationId);
        imMessageOnlineSend.setWithdraw(message.getWithdraw());
        imMessageOnlineSend.setEvent(message.getEvent());

        //  向接收方推送
        WsResponse<ImMessageOnlineSend> responseModel = new WsResponse<>();
        responseModel.setCmd(WsResponseCmdEnum.CONVERSATION_EVENT_MSG.getCmdCode());
        ApiResult<Boolean> result = ApiResult.result(ApiCode.SUCCESS);
        responseModel.setCode(result.getCode());
        responseModel.setMsg(result.getMessage());
        responseModel.setData(imMessageOnlineSend);
        responseModel.setReqId(null);
        channelSender.sendMsg(responseModel, receiverClientId);
    }

}
