package com.wecloud.im.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversationMembers;
import com.wecloud.im.entity.ImMessageOnlineSend;
import com.wecloud.im.mapper.ImConversationMapper;
import com.wecloud.im.mapper.ImConversationMembersMapper;
import com.wecloud.im.param.*;
import com.wecloud.im.param.add.ImConversationMemAttrUpdate;
import com.wecloud.im.service.*;
import com.wecloud.im.vo.ConversationMemberVo;
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.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 会话成员表 服务实现类
 *
 * @author wei
 * @since 2021-05-07
 */
@Slf4j
@Service
public class ImConversationMembersServiceImpl extends BaseServiceImpl<ImConversationMembersMapper, ImConversationMembers> implements ImConversationMembersService {

    @Autowired
    private ChannelSender channelSender;

    @Autowired
    private ImConversationMapper imConversationMapper;

    @Autowired
    private ImConversationMembersService imConversationMembersService;

    @Autowired
    private ImConversationService imConversationService;

    @Autowired
    private ImClientService imClientService;

    @Autowired
    private ImApplicationService imApplicationService;

    @Autowired
    private ImMessageService imMessageService;

    @Autowired
    private ImConversationMembersMapper imConversationMembersMapper;

    @Autowired
    private ContextService contextService;

    @Override
    public ApiResult<List<ApiImConversationMembersQueryVo>> getRestApiImConversationMembersList(ApiImConversationMembersPageParam apiImConversationMembersPageParam, ImApplication imApplication) {

        List<ApiImConversationMembersQueryVo> restApiImConversationMembersList = imConversationMembersMapper.getRestApiImConversationMembersList(apiImConversationMembersPageParam.getConversationId());
        return ApiResult.ok(restApiImConversationMembersList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateClientRemarkName(ImConvMemeClientRemarkNameParam param) {
        ImClient currentClient = imClientService.getCurrentClient();
        // 查询该成员
        ImConversationMembers imConversationMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, currentClient.getFkAppid())
                        .eq(ImConversationMembers::getFkConversationId, param.getConversationId())
                        .eq(ImConversationMembers::getFkClientId, currentClient.getId())
        );
        if (imConversationMember == null) {
            throw new BusinessException("未查询到会话成员信息");
        }
        imConversationMember.setClientRemarkName(param.getClientRemarkName());
        boolean b = imConversationMembersService.updateById(imConversationMember);
        if (!b) {
            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())
        );
        for (ImConversationMembers member : membersList) {
            // 不关心事件是否发送成功
            try {
                // 给所有成员下发事件消息
                ImClient imClientReceiver = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                        .eq(ImClient::getFkAppid, currentClient.getFkAppid())
                        .eq(ImClient::getId, member.getFkClientId()));
                if (imClientReceiver == null) {
                    continue;
                }

                // 封装响应的实体
                ImMessageOnlineSend imMessageOnlineSend = new ImMessageOnlineSend();
                imMessageOnlineSend.setCreateTime(new Date());
                imMessageOnlineSend.setType(MsgTypeEnum.CONVERSATION_MEMBER_NAME_MODIFY.getUriCode());
                imMessageOnlineSend.setSender(currentClient.getClientId());
                Map<String, Object> content = Maps.newHashMap();
                content.put("operator", currentClient.getClientId());
                content.put("remarkName", param.getClientRemarkName());
                imMessageOnlineSend.setContent(content);
                imMessageOnlineSend.setConversationId(param.getConversationId());
                imMessageOnlineSend.setWithdraw(Boolean.FALSE);
                imMessageOnlineSend.setEvent(Boolean.TRUE);

                //  向接收方推送
                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, imClientReceiver.getId());
            } catch (Exception e) {
                log.info("下发解散群事件失败，接收人 {}", JSON.toJSONString(member));
            }
        }
    }

    @Override
    public List<ConversationMemberVo> getImConversationMembersList(ListConversationMembersParam param) {
        return imConversationMembersMapper.getImConversationMembersList(param);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveOrUpdateAttr(ImConversationMemAttrUpdate imConversationMemAttrUpdate) {

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

        ImClient imClientSender = imClientService.getCurrentClient();

        // 查询该成员
        ImConversationMembers imConversationMember = imConversationMembersService.getOne(
                new QueryWrapper<ImConversationMembers>().lambda()
                        .eq(ImConversationMembers::getFkAppid, imApplication.getId())
                        .eq(ImConversationMembers::getFkConversationId, imConversationMemAttrUpdate.getConversationId())
                        .eq(ImConversationMembers::getId, imClientSender.getId())
        );

        if (imConversationMember == null) {
            return 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())
//        );

        String attributes = JsonUtils.encodeJson(imConversationMemAttrUpdate.getAttributes());
        imConversationMember.setAttributes(attributes);


        boolean b = imConversationMembersService.updateById(imConversationMember);
        //TODO ws下发群成员属性变动事件
        return b;

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveImConversationMembers(ImConversationMembers imConversationMembers) throws Exception {
        return super.save(imConversationMembers);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateImConversationMembers(ImConversationMembers imConversationMembers) throws Exception {
        return super.updateById(imConversationMembers);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean deleteImConversationMembers(Long id) {
        return super.removeById(id);
    }

    @Override
    public void deleteByConversationId(Long conversationId) {
        imConversationMembersMapper.deleteByConversationId(conversationId);
    }

    @Override
    public ImConversationMembersQueryVo getImConversationMembersById(Long id) throws Exception {
        return imConversationMembersMapper.getImConversationMembersById(id);
    }

    @Override
    public Paging<ImConversationMembersQueryVo> getImConversationMembersPageList(ImConversationMembersPageParam imConversationMembersPageParam) throws Exception {
        Page<ImConversationMembersQueryVo> page = new PageInfo<>(imConversationMembersPageParam, OrderItem.desc(getLambdaColumn(ImConversationMembers::getCreateTime)));
        IPage<ImConversationMembersQueryVo> iPage = imConversationMembersMapper.getImConversationMembersPageList(page, imConversationMembersPageParam);
        return new Paging<ImConversationMembersQueryVo>(iPage);
    }

    @Override
    public List<Long> findThousandGroupsByClientId(Long clientId) {
        return imConversationMembersMapper.findThousandGroupsByClientId(clientId);
    }

    /**
     * 批量设置群成员
     * @param param
     * @param fkClientIds
     */
    @Override
    public void setAdminsForConversation(SetAdminsParam param, List<Long> fkClientIds) {
        Integer role = param.getOperateType() == 1 ? 2 : 1;
        imConversationMembersMapper.setAdminsForConversation(param.getConversationId(), fkClientIds, role);
    }

}
