package com.wecloud.im.service.impl;

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.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;
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.ImConversationPageParam;
import com.wecloud.im.param.ImConversationQueryVo;
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.ImConversationRestApiCreate;
import com.wecloud.im.service.ImApplicationService;
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.ImConversationCreateVo;
import com.wecloud.im.vo.MyConversationListVo;
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.WsResponseModel;
import com.wecloud.im.ws.service.WriteDataService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
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 io.geekidea.springbootplus.framework.shiro.jwt.JwtToken;
import io.geekidea.springbootplus.framework.shiro.util.JwtUtil;
import io.geekidea.springbootplus.framework.shiro.util.SnowflakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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


    private static final JsonMapper JSON_MAPPER = new JsonMapper();

    @Autowired
    private WriteDataService writeDataService;

    @Autowired
    private ImConversationMapper imConversationMapper;

    @Autowired
    private ImConversationMembersService imConversationMembersService;

    @Autowired
    private ImConversationService imConversationService;

    @Autowired
    private ImClientService imClientService;

    @Autowired
    private ImApplicationService imApplicationService;

    @Autowired
    private ImMessageService imMessageService;

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<ImConversationCreateVo> createImConversation(ImConversationCreate imConversationCreate) throws JsonProcessingException {

        ImClient createClient = imClientService.getCurentClient();

        if (imConversationCreate.getClientIds().size() == 0) {
            log.info("没有成员");
            return ApiResult.result(ApiCode.CLIENT_NOT_FOUNT, null);
        }

        // 成员不存在,不能创建会话
        for (String id : imConversationCreate.getClientIds()) {
            ImClient imClient = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .select(ImClient::getId)
                    .eq(ImClient::getFkAppid, createClient.getFkAppid())
                    .eq(ImClient::getClientId, id));
            if (imClient == null) {
                log.info("成员不存在,不能创建会话 client2 == null");
                return ApiResult.result(ApiCode.CLIENT_NOT_FOUNT, null);
            }
        }

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询application
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());

        // 该应用 是否允许创建重复一对一会话 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)));

                // 是否存在重复一对一会话
                Integer repetitionConversation = getRepetitionConversation(createClient.getId(), client2.getId());
                if (repetitionConversation != 0) {

                    log.info("repetitionConversation != 0");
                    // 返回已存在的一对一会话id
                    ImConversation repetitionConversationInfo = imConversationMapper.getRepetitionConversationInfo(createClient.getId(), client2.getId());
                    ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
                    imConversationCreateVo.setId(repetitionConversationInfo.getId());

                    return ApiResult.ok(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)));
                JsonMapper jsonMapper = new JsonMapper();
                String asString = jsonMapper.writeValueAsString(imConversationCreate.getAttributes());
                log.info("RequestAttributes:" + asString);


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

                // 存在重复会话
                if (repetitionConversation != null) {
                    log.info("出现Attributes重复");
                    ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
                    imConversationCreateVo.setId(repetitionConversation);
                    // 为重复
                    return ApiResult.ok(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.setName(imConversationCreate.getName());
        imConversation.setSystem(false);
        JsonMapper jsonMapper = new JsonMapper();
        // 拓展数据
        String writeValueAsString = jsonMapper.writeValueAsString(imConversationCreate.getAttributes());
        imConversation.setAttributes(writeValueAsString);
        imConversationService.save(imConversation);

        // 将创建者自己添加到会话
        Long imConversationMembersId = SnowflakeUtil.getId();
        ImConversationMembers imConversationMembers = new ImConversationMembers();
        imConversationMembers.setId(imConversationMembersId);
        imConversationMembers.setCreateTime(new Date());
        imConversationMembers.setFkAppid(createClient.getFkAppid());
        imConversationMembers.setFkConversationId(imConversationId);
        imConversationMembers.setFkClientId(creator);
        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));
            Long imConversationMembersId2 = SnowflakeUtil.getId();
            ImConversationMembers imConversationMembers2 = new ImConversationMembers();
            imConversationMembers2.setId(imConversationMembersId2);
            imConversationMembers2.setCreateTime(new Date());
            imConversationMembers2.setFkAppid(createClient.getFkAppid());
            imConversationMembers2.setFkConversationId(imConversationId);
            imConversationMembers2.setFkClientId(client2.getId());
            imConversationMembersService.save(imConversationMembers2);
        }

        ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
        imConversationCreateVo.setId(imConversationId);

        return ApiResult.ok(imConversationCreateVo);
    }

    @Override
    public ApiResult<ImConversationCreateVo> createImConversationRestApi(ImConversationRestApiCreate imConversationRestApiCreate, String appkey, String appSecret) throws JsonProcessingException {

        if (imConversationRestApiCreate.getClientIds().size() == 0) {
            log.info("没有成员");
            return ApiResult.result(ApiCode.CLIENT_NOT_FOUNT, null);
        }

        //  根据appKey查询appid
        ImApplication imApplication = imApplicationService.getOneByAppKey(appkey);

        // 创建者
        ImClient createClient = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, imApplication.getId())
                .eq(ImClient::getClientId, imConversationRestApiCreate.getCreator()));

        if (createClient == null) {
            log.info("没有创建者");
            return ApiResult.result(ApiCode.CLIENT_NOT_FOUNT, null);
        }

        // 成员不存在,不能创建会话
        for (String id : imConversationRestApiCreate.getClientIds()) {
            ImClient imClient = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .select(ImClient::getId)
                    .eq(ImClient::getFkAppid, imApplication.getId())
                    .eq(ImClient::getClientId, id));
            if (imClient == null) {
                log.info("成员不存在,不能创建会话 client2 == null");
                return ApiResult.result(ApiCode.CLIENT_NOT_FOUNT, null);
            }
        }
        // 该应用 是否允许创建重复一对一会话 0不允许 1允许
        if (imApplication.getRepeatSessionStatus() != null && imApplication.getRepeatSessionStatus() == 0) {
            // 判断是否已经存在一对一会话
            // size() == 1 为单聊不允许重复创建 两个用户如果已经创建过会话,不能重复创建会话
            if (imConversationRestApiCreate.getClientIds().size() == 1) {
                ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, createClient.getFkAppid())
                        .eq(ImClient::getClientId, imConversationRestApiCreate.getClientIds().get(0)));

                // 是否存在重复一对一会话
                Integer repetitionConversation = getRepetitionConversation(createClient.getId(), client2.getId());
                if (repetitionConversation != 0) {

                    log.info("repetitionConversation != 0");
                    // 返回已存在的一对一会话id
                    ImConversation repetitionConversationInfo = imConversationMapper.getRepetitionConversationInfo(createClient.getId(), client2.getId());
                    ImConversationCreateVo createVo = new ImConversationCreateVo();
                    createVo.setId(repetitionConversationInfo.getId());

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

            //创建重复一对一会话时对比扩展字段  1是
            if (imApplication.getContrastExtendedFieldStatus() == 1) {

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

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

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

        // 会话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.setName(imConversationRestApiCreate.getName());
        imConversation.setSystem(false);
        JsonMapper jsonMapper = new JsonMapper();
        // 拓展数据
        String writeValueAsString = jsonMapper.writeValueAsString(imConversationRestApiCreate.getAttributes());
        imConversation.setAttributes(writeValueAsString);
        imConversationService.save(imConversation);

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

        // 将他人添加到会话
        for (String id : imConversationRestApiCreate.getClientIds()) {
            ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, createClient.getFkAppid())
                    .eq(ImClient::getClientId, id));
            Long imConversationMembersId2 = SnowflakeUtil.getId();
            ImConversationMembers imConversationMembers2 = new ImConversationMembers();
            imConversationMembers2.setId(imConversationMembersId2);
            imConversationMembers2.setCreateTime(new Date());
            imConversationMembers2.setFkAppid(createClient.getFkAppid());
            imConversationMembers2.setFkConversationId(imConversationId);
            imConversationMembers2.setFkClientId(client2.getId());
            imConversationMembersService.save(imConversationMembers2);
        }

        ImConversationCreateVo createVo = new ImConversationCreateVo();
        createVo.setId(imConversationId);
        return ApiResult.ok(createVo);
    }

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

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();

        ImClient imClientSender = imClientService.getCurentClient();

        if (addMember(imClientToConversation, curentJwtToken.getAppKey(), imClientSender)) {
            return ApiResult.fail();
        }
        return ApiResult.ok();

    }

    private boolean addMember(ImClientToConversation imClientToConversation, String appKey, ImClient imClientSender) {
        //  根据appKey查询application
        ImApplication imApplication = imApplicationService.getOneByAppKey(appKey);

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

                        .eq(ImConversationMembers::getFkConversationId, imClientToConversation.getConversationId())
                        .notIn(ImConversationMembers::getId, imClientSender.getId())
        );
        if (membersList.isEmpty()) {
            log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
            return true;
        }

        // 将他人添加到会话
        for (String id : imClientToConversation.getClientIds()) {

            ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, imApplication.getId())
                    .eq(ImClient::getClientId, id));

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

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

            Long imConversationMembersId2 = SnowflakeUtil.getId();
            ImConversationMembers imConversationMembers2 = new ImConversationMembers();
            imConversationMembers2.setId(imConversationMembersId2);
            imConversationMembers2.setCreateTime(new Date());
            imConversationMembers2.setFkAppid(imApplication.getId());
            imConversationMembers2.setFkConversationId(imClientToConversation.getConversationId());
            imConversationMembers2.setFkClientId(client2.getId());
            imConversationMembersService.save(imConversationMembers2);

            // 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", client2.getClientId()); //被操作的client ID
            content.put("type", MsgTypeEnum.INVITE_CLIENT_JOIN_CONVERSATION.getUriCode()); //xx邀请xx加入会话 -1007
            try {
                String contentString = JSON_MAPPER.writeValueAsString(content);
                imMessage.setContent(contentString);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

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

            //推送到被拉入方
            Long fkConversationId = imClientToConversation.getConversationId();
            String clientId = imClientSender.getClientId();
            String toClientId = client2.getClientId();
            String imApplicationAppKey = imApplication.getAppKey();
            sendEventMsg(messageId, (HashMap) content, fkConversationId, clientId, toClientId, imApplicationAppKey);

            // 遍历发送
            for (ImConversationMembers conversationMembers : membersList) {

                // 查询接收方
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, imApplication.getId())
                        .eq(ImClient::getId, conversationMembers.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }

                sendEventMsg(messageId, (HashMap) content, conversationMembers.getFkConversationId(), imClientSender.getClientId(), imClientReceiver.getClientId(), imApplication.getAppKey());

            }

        }
        return false;
    }

    private void sendEventMsg(long messageId, HashMap content, Long fkConversationId, String clientId, String toClientId, String imApplicationAppKey) {
        // 封装响应的实体
        ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();


        imMessageOnlineSend.setMsgId(messageId);
        imMessageOnlineSend.setSender(clientId);
        imMessageOnlineSend.setContent(content);
        imMessageOnlineSend.setConversationId(fkConversationId);
        imMessageOnlineSend.setWithdraw(Boolean.FALSE);
        imMessageOnlineSend.setEvent(Boolean.TRUE);

        //  向接收方推送
        WsResponseModel<ImMessageOnlineSend> responseModel = new WsResponseModel<>();
        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);
        writeDataService.write(responseModel, imApplicationAppKey, toClientId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> delClientToConversation(ImClientToConversation imClientToConversation) throws Exception {

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询application
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());

        ImClient imClientSender = imClientService.getCurentClient();

        // 判断是否为群主
        ImConversation imConversationById = imConversationService.getById(imClientToConversation.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, imClientToConversation.getConversationId())
                        .notIn(ImConversationMembers::getId, imClientSender.getId())
        );
        if (membersList.isEmpty()) {
            log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
            return ApiResult.fail();
        }

        // 将client从会话移除
        for (String id : imClientToConversation.getClientIds()) {

            ImClient client2 = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, imApplication.getId())
                    .eq(ImClient::getClientId, id));

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

            // 则跳过
            imConversationMembersService.deleteImConversationMembers(members.getId());

            // 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", client2.getClientId()); //被操作的client ID
            content.put("type", MsgTypeEnum.REMOVE_CLIENT_CONVERSATION.getUriCode()); //xx被xx移出会话 -1008
            try {
                String asString = JSON_MAPPER.writeValueAsString(content);
                imMessage.setContent(asString);

            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }

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

            // 遍历发送
            for (ImConversationMembers conversationMembers : membersList) {

                // 查询接收方
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, imApplication.getId())
                        .eq(ImClient::getId, conversationMembers.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }

                // 封装响应的实体
                sendEventMsg(messageId, (HashMap) content, conversationMembers.getFkConversationId(), imClientSender.getClientId(), imClientReceiver.getClientId(), imApplication.getAppKey());

            }

        }
        return ApiResult.ok();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> leaveConversation(ImClientLeaveConversation imClientToConversation) throws Exception {

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询application
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());

        ImClient imClientSender = imClientService.getCurentClient();

        ImConversation imConversationById = imConversationService.getById(imClientToConversation.getConversationId());
        if (imConversationById == null) {
            throw new Exception("imConversationById == null");
        }

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

        if (membersList.isEmpty()) {
            log.info("membersList为空,toConversationId:" + imClientToConversation.getConversationId());
            throw new Exception("deleteImConversationMembers");
        }

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

        // 将client从会话移除
        boolean b = imConversationMembersService.deleteImConversationMembers(members.getId());
        if (!b) {
            throw new Exception("deleteImConversationMembers");
        }

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


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

        Map<String, Object> content = new HashMap<>();
        content.put("type", MsgTypeEnum.LEAVE_CONVERSATION.getUriCode()); // xx主动退出会话
        try {
            String asString = JSON_MAPPER.writeValueAsString(content);
            imMessage.setContent(asString);

        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        //  保存消息至消息表
        imMessage.setId(messageId);
        imMessage.setCreateTime(new Date());
        imMessage.setFkAppid(imApplication.getId());
        imMessage.setSender(imClientSender.getId());
        imMessage.setWithdraw(false);
        imMessage.setEvent(true);
        imMessage.setSystem(false);
        imMessage.setSendStatus(2);
        imMessage.setFkConversationId(imClientToConversation.getConversationId());
        boolean save = imMessageService.save(imMessage);
        if (!save) {
            throw new Exception("deleteImConversationMembers");
        }

        // 遍历发送
        for (ImConversationMembers conversationMembers : membersList) {

            // 查询接收方
            ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                    .eq(ImClient::getFkAppid, imApplication.getId())
                    .eq(ImClient::getId, conversationMembers.getFkClientId()));
            if (imClientReceiver == null) {
                continue;
            }

            // 封装响应的实体
            sendEventMsg(messageId, (HashMap) content, conversationMembers.getFkConversationId(), imClientSender.getClientId(), imClientReceiver.getClientId(), imApplication.getAppKey());

        }


        //   群主退出 是否需要转移给下一个人
        if (imConversationById.getCreator().equals(imClientSender.getId()) && imClientToConversation.getTransfer()) {
            ImConversationMembers conversationMember = membersList.get(0);
            imConversationById.setCreator(conversationMember.getFkClientId());

            // 创建者权限转移给下一个人
            imConversationService.updateById(imConversationById);

        }


        return ApiResult.ok();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> saveOrUpdateName(ImConversationNameUpdate imConversationNameUpdate) throws Exception {

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询application
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());

        ImClient imClientSender = imClientService.getCurentClient();

        ImConversation imConversationById = imConversationService.getById(imConversationNameUpdate.getConversationId());

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

        // 查询该会话所有成员
        List<ImConversationMembers> membersList = imConversationMembersService.list(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkConversationId, imConversationNameUpdate.getConversationId())
                        .notIn(ImConversationMembers::getId, imClientSender.getId())
        );

        imConversationById.setName(imConversationNameUpdate.getName());
        boolean b = imConversationService.updateById(imConversationById);
        if (b) {
            // 下发群名称变动事件


            // ws下发群属性变动事件

            // 内容
            HashMap<String, String> content = new HashMap<>();
            content.put("type", "-1015");
            content.put("name", imConversationById.getName());


            // 遍历发送
            for (ImConversationMembers conversationMembers : membersList) {

                // 查询接收方
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, imApplication.getId())
                        .eq(ImClient::getId, conversationMembers.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }

                // 封装响应的实体
                ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();

//                imMessageOnlineSend.setMsgId(null);
//                imMessageOnlineSend.setSender(imClientSender.getClientId());
                imMessageOnlineSend.setContent(content);
                imMessageOnlineSend.setConversationId(conversationMembers.getFkConversationId());
//                imMessageOnlineSend.setWithdraw(Boolean.FALSE);
                imMessageOnlineSend.setEvent(Boolean.TRUE);

                //  向接收方推送
                WsResponseModel<ImMessageOnlineSend> responseModel = new WsResponseModel<>();
                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);
                writeDataService.write(responseModel, imApplication.getAppKey(), imClientReceiver.getClientId());
            }

            return ApiResult.ok();

        } else {
            return ApiResult.fail();
        }


    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ApiResult<Boolean> saveOrUpdateAttr(ImConversationAttrUpdate imConversationAttrUpdate) throws Exception {

        // shiro线程中获取当前token
        JwtToken curentJwtToken = JwtUtil.getCurentJwtToken();
        //  根据appKey查询application
        ImApplication imApplication = imApplicationService.getOneByAppKey(curentJwtToken.getAppKey());

        ImClient imClientSender = imClientService.getCurentClient();

        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())
                        .notIn(ImConversationMembers::getId, imClientSender.getId())
        );

        JsonMapper jsonMapper = new JsonMapper();

        try {
            String attributes = jsonMapper.writeValueAsString(imConversationAttrUpdate.getAttributes());

            imConversationById.setAttributes(attributes);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return ApiResult.fail();
        }

        boolean b = imConversationService.updateById(imConversationById);
        if (b) {


            // ws下发拓展字段变动事件

            // 内容
            HashMap<String, String> content = new HashMap<>();
            content.put("type", "-1014");
            content.put("attributes", imConversationById.getAttributes());


            // 遍历发送
            for (ImConversationMembers conversationMembers : membersList) {

                // 查询接收方
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, imApplication.getId())
                        .eq(ImClient::getId, conversationMembers.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }

                // 封装响应的实体
                ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();

//                imMessageOnlineSend.setMsgId(null);
//                imMessageOnlineSend.setSender(imClientSender.getClientId());
                imMessageOnlineSend.setContent(content);
                imMessageOnlineSend.setConversationId(conversationMembers.getFkConversationId());
//                imMessageOnlineSend.setWithdraw(Boolean.FALSE);
                imMessageOnlineSend.setEvent(Boolean.TRUE);

                //  向接收方推送
                WsResponseModel<ImMessageOnlineSend> responseModel = new WsResponseModel<>();
                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);
                writeDataService.write(responseModel, imApplication.getAppKey(), imClientReceiver.getClientId());

            }


            return ApiResult.ok();

        } else {
            return ApiResult.fail();
        }

    }

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


    /**
     * 是否单向隐藏会话","云端聊天记录不删除;假设有A和B两个用户,A删会话,B还能发; 如果B发了消息,A这边要重新把会话显示出来,并能显示之前的聊天记录"
     *
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateDisplayConversation(ImConversationDisplayUpdate imConversationDisplayUpdate) throws Exception {
        ImClient curentClient = imClientService.getCurentClient();
        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
    public ImConversationQueryVo getImConversationById(Long id) throws Exception {
        return imConversationMapper.getImConversationById(id);
    }


    @Override
    public MyConversationListVo getImConversationAndMsgCountById(Long clientId, Long conversationId) {
        return imConversationMapper.getImConversationAndMsgCountById(clientId, conversationId);
    }


    @Override
    public MyConversationListVo getImConversationInfoById(Long id) throws Exception {

        ImClient client = imClientService.getCurentClient();

        MyConversationListVo imConversationAndMsgCountById = this.getImConversationAndMsgCountById(client.getId(), id);

        JsonMapper jsonMapper = new JsonMapper();
        HashMap attributess = jsonMapper.readValue(imConversationAndMsgCountById.getAttribute(), HashMap.class);
        imConversationAndMsgCountById.setAttributes(attributess);

        return imConversationAndMsgCountById;
    }

    @Override
    public MyConversationListVo getImConversationInfoByIdForServerApi(Long id) throws Exception {
        MyConversationListVo imConversationAndMsgCountById = imConversationMapper.getImConversationInfoByIdForServerApi(id);
        JsonMapper jsonMapper = new JsonMapper();
        HashMap attributess = jsonMapper.readValue(imConversationAndMsgCountById.getAttribute(), HashMap.class);
        imConversationAndMsgCountById.setAttributes(attributess);
        return imConversationAndMsgCountById;
    }

    @Override
    public Paging<ImConversationQueryVo> getImConversationPageList(ImConversationPageParam imConversationPageParam) throws Exception {
        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<MyConversationListVo> getMyImConversationListAndMsgCount() throws Exception {

        ImClient client = imClientService.getCurentClient();

        // 查询用户加入的所有会话 与每个会话的未读条数 成员
        List<MyConversationListVo> myImConversationListAndMsgCount = imConversationMapper.getMyImConversationListAndMsgCount(client.getId());
        JsonMapper jsonMapper = new JsonMapper();

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

        // 转换json格式
        for (MyConversationListVo myconversationlistvo : myImConversationListAndMsgCount) {
            HashMap attributess = jsonMapper.readValue(myconversationlistvo.getAttribute(), HashMap.class);
            myconversationlistvo.setAttributes(attributess);

            // 查询会话的最后一条消息
            OfflineMsgDto lastMsg = imMessageService.getLastMsgByConversationId(myconversationlistvo.getId());
            myconversationlistvo.setLastMsg(lastMsg);

            myImConversationListAndMsgCountNew.add(myconversationlistvo);

        }
        return myImConversationListAndMsgCountNew;

    }


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

    @Override
    public Integer getRepetitionConversation(Long clientId1, Long clientId2) {
        return imConversationMapper.getRepetitionConversation(clientId1, clientId2);
    }

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

}
