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.mapper.ImConversationMapper;
import com.wecloud.im.param.ImConversationPageParam;
import com.wecloud.im.param.ImConversationQueryVo;
import com.wecloud.im.param.add.ImConversationCreate;
import com.wecloud.im.param.add.ImConversationDisplayUpdate;
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 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.LinkedHashMap;
import java.util.List;

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

    @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();

        // 成员不存在,不能创建会话
        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 {

            //创建重复会话时对比扩展字段  0不  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)));

                // 是否存在重复会话
                Integer repetitionConversation = getRepetitionConversation(createClient.getId(), inviteClient.getId());
                if (repetitionConversation != 0) {
                    ImConversation repetitionConversationInfo = imConversationMapper.getRepetitionConversationInfo(createClient.getId(), inviteClient.getId());

                    JsonMapper jsonMapper = new JsonMapper();
                    LinkedHashMap linkedHashMap = jsonMapper.readValue(repetitionConversationInfo.getAttributes(), LinkedHashMap.class);

                    if (linkedHashMap.equals(imConversationCreate.getAttributes())) {
                        log.info(imConversationCreate.getAttributes() + ",出现重复");
                        ImConversationCreateVo imConversationCreateVo = new ImConversationCreateVo();
                        imConversationCreateVo.setId(repetitionConversationInfo.getId());
                        // 为重复
                        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);
    }

    @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 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);
    }

}
