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

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.microsvc.toolkit.middleware.im.ImPluginContext;
import com.microsvc.toolkit.middleware.im.message.ETencentMessage;
import com.microsvc.toolkit.middleware.im.message.MessageWrapper;
import com.microsvc.toolkit.middleware.im.message.TencentRequest;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.dao.ImGroupDao;
import com.yonge.cooleshow.biz.dal.dao.ImGroupNoticeDao;
import com.yonge.cooleshow.biz.dal.dto.ImGroupNoticeDto;
import com.yonge.cooleshow.biz.dal.entity.ImGroup;
import com.yonge.cooleshow.biz.dal.entity.ImGroupNotice;
import com.yonge.cooleshow.biz.dal.service.ImGroupNoticeService;
import com.yonge.cooleshow.biz.dal.service.ImGroupService;
import com.yonge.cooleshow.biz.dal.wrapper.im.ImGroupNoticeWrapper;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.page.PageInfo;
import com.yonge.toolset.mybatis.support.PageUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * 群公告(ImGroupNotice)表服务实现类
 *
 * @author zx
 * @since 2022-03-22 10:45:59
 */
@Service("imGroupNoticeService")
public class ImGroupNoticeServiceImpl extends ServiceImpl<ImGroupNoticeDao, ImGroupNotice> implements ImGroupNoticeService {

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

    @Resource
    private SysUserFeignService sysUserFeignService;
    @Resource
    private ImGroupService imGroupService;
    @Resource
    private ImPluginContext imPluginContext;

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(ImGroupNoticeDto imGroupNotice) {
        Long userId = this.checkAdmin(imGroupNotice.getGroupId());
        Date date = new Date();
        imGroupNotice.setOperatorId(userId);
        imGroupNotice.setCreateTime(date);
        imGroupNotice.setUpdateTime(date);

        // 群公告置顶 只能有一个
        if(imGroupNotice.getTopFlag() != null && Boolean.TRUE.equals(imGroupNotice.getTopFlag())){
            baseMapper.updateTopFlag(imGroupNotice.getGroupId());
        }
        baseMapper.insert(imGroupNotice);
        // 发送群公告消息
        String messageSeqId = sendGroupCustomNoticeMessage(convertToImGroupNotice(imGroupNotice));
        // 更新群公告消息ID
        if (StringUtils.isNotBlank(messageSeqId)) {
            imGroupNotice.setMessageSeqId(messageSeqId);
            baseMapper.updateById(imGroupNotice);
        }
    }

    public ImGroupNoticeWrapper.ImGroupNotice convertToImGroupNotice(ImGroupNoticeDto imGroupNotice) {
        ImGroupNoticeWrapper.ImGroupNotice notice = ImGroupNoticeWrapper.ImGroupNotice.builder()
                .id(imGroupNotice.getId())
                .groupId(imGroupNotice.getGroupId())
                .title(imGroupNotice.getTitle())
                .content(imGroupNotice.getContent())
                .topFlag(imGroupNotice.getTopFlag())
                .clientType(imGroupNotice.getClientType())
                .sentToNewMemberFlag(imGroupNotice.getSentToNewMemberFlag())
                .operatorId(imGroupNotice.getOperatorId())
                .delFlag(imGroupNotice.getDelFlag())
                .build();
        return notice;
    }

    @Override
    public void del(Long noticeId) {
        ImGroupNotice imGroupNotice = baseMapper.selectById(noticeId);
        if(Objects.isNull(imGroupNotice)){
            throw new BizException("该群公告已被删除");
        }
        this.checkAdmin(imGroupNotice.getGroupId());
        baseMapper.deleteById(noticeId);
        // 撤销群公告消息
        revokeImGroupNoticeMessage(imGroupNotice);
    }

    @Override
    public PageInfo<ImGroupNoticeDto> queryPage(Map<String,Object> params) {
        Page<ImGroupNoticeDto> pageInfo = PageUtil.getPageInfo(params);
        pageInfo.setDesc("top_flag_","id_");
        return PageUtil.pageInfo(baseMapper.queryPage(pageInfo,params));
    }

    @Override
    public ImGroupNoticeDto getNotice(Long noticeId) {
        ImGroupNotice imGroupNotice = baseMapper.selectById(noticeId);
        if(Objects.isNull(imGroupNotice)){
            throw new BizException("该群公告已被删除");
        }
        ImGroupNoticeDto imGroupNoticeDto = JSON.parseObject(JSON.toJSONString(imGroupNotice), ImGroupNoticeDto.class);
        SysUser sysUser = sysUserFeignService.queryUserById(imGroupNotice.getOperatorId());
        imGroupNoticeDto.setUsername(sysUser.getUsername());
        imGroupNoticeDto.setAvatar(sysUser.getAvatar());
        return imGroupNoticeDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modify(ImGroupNoticeDto imGroupNotice) {
        if(Objects.isNull(baseMapper.selectById(imGroupNotice.getId()))){
            throw new BizException("该群公告已被删除");
        }
        Long userId = this.checkAdmin(imGroupNotice.getGroupId());
        Date date = new Date();
        imGroupNotice.setOperatorId(userId);
        imGroupNotice.setCreateTime(date);
        imGroupNotice.setUpdateTime(date);

        // 群公告置顶 只能有一个
        if(imGroupNotice.getTopFlag() != null && Boolean.TRUE.equals(imGroupNotice.getTopFlag())){
            baseMapper.updateTopFlag(imGroupNotice.getGroupId());
        }
        baseMapper.updateById(imGroupNotice);
        // 撤销群公告消息
        ImGroupNotice notice = baseMapper.selectById(imGroupNotice.getId());
        revokeImGroupNoticeMessage(notice);
        // 发送群公告消息
        ImGroupNoticeDto dto = JSON.parseObject(JSON.toJSONString(notice), ImGroupNoticeDto.class);
        dto.setClientType(imGroupNotice.getClientType());
        String messageSeqId = sendGroupCustomNoticeMessage(convertToImGroupNotice(dto));

        // 更新群公告消息ID
        if (StringUtils.isNotBlank(messageSeqId)) {
            notice.setMessageSeqId(messageSeqId);
            baseMapper.updateById(notice);
        }
    }

    public Long checkAdmin(String groupId){
        ImGroup imGroup = imGroupService.getById(groupId);
        if(Objects.isNull(imGroup)){
            throw new BizException("该群公告已被删除");
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if(!Objects.equals(sysUser.getId(),imGroup.getCreateBy())){
            throw new BizException("您没有操作权限");
        }
        return sysUser.getId();
    }

    /**
     * 发送群公告消息
     *
     * @param notice   ImGroupNoticeWrapper.ImGroupNotice
     * @return 消息ID
     */
    private String sendGroupCustomNoticeMessage(ImGroupNoticeWrapper.ImGroupNotice notice) {
        String messageSeqId;
        // 发送群公告消息
        ImGroupNoticeWrapper.CustomGroupNotice customGroupNotice = ImGroupNoticeWrapper.CustomGroupNotice.builder()
                .businessID("TC_GROUP_NOTICE")
                .msgId(String.valueOf(notice.getId()))
                .msgTitle(notice.getTitle())
                .msgContent(notice.getContent())
                .build();

        TencentRequest.MessageBody messageBody = TencentRequest.MessageBody.builder()
                .msgType(ETencentMessage.TIMCustomElem.name())
                .msgContent(TencentRequest.CustomMessageBody.builder()
                        .data(customGroupNotice.jsonString())
                        .desc("群公告")
                        .build())
                .build();

        try {
            // 发送群公告消息
            messageSeqId = imPluginContext.getPluginService().sendGroupMessage(MessageWrapper.GroupMessage.builder()
                    .senderId(imGroupService.getImUserId(notice.getOperatorId().toString(), notice.getClientType()))
                    .groupId(notice.getGroupId())
                    .tencentMessage(messageBody)
                    .build());
        } catch (Exception e) {
            log.error("群公告消息发送失败, messageId={}, groupId={}, title={}, ", notice.getId(), notice.getGroupId(),
                    notice.getTitle(), e);
            throw com.microsvc.toolkit.common.webportal.exception.BizException.from("群公告消息发送失败");
        }
        return messageSeqId;
    }

    /**
     * 撤销群公告消息
     * @param imGroupNotice ImGroupNotice
     */
    private void revokeImGroupNoticeMessage(ImGroupNotice imGroupNotice) {
        try {
            if (StringUtils.isNotBlank(imGroupNotice.getMessageSeqId())) {
                imPluginContext.getPluginService().recallGroupMessage(MessageWrapper.RecallGroupMessage.builder()
                        .groupId(imGroupNotice.getGroupId())
                        .reason("群公告消息撤销")
                        .messageSeqs(Lists.newArrayList(
                                TencentRequest.GroupMessageSeq.builder().messageSeq(Integer.parseInt(imGroupNotice.getMessageSeqId())).build()
                        ))
                        .build());
            }
        } catch (Exception e) {
            log.error("撤销群公告消息失败, messageId={}, groupId={}, title={}, ", imGroupNotice.getId(), imGroupNotice.getGroupId(),
                    imGroupNotice.getTitle(), e);
        }
    }

}

