package com.gxwebsoft.love.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.service.UserService;
import com.gxwebsoft.love.entity.ChatConversation;
import com.gxwebsoft.love.entity.ChatMessage;
import com.gxwebsoft.love.enums.ChatMessageType;
import com.gxwebsoft.love.mapper.ChatMessageMapper;
import com.gxwebsoft.love.param.ChatMessageParam;
import com.gxwebsoft.love.service.ChatConversationService;
import com.gxwebsoft.love.service.ChatMessageService;
import com.gxwebsoft.love.socketio.cache.ClientCache;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 聊天消息表Service实现
 *
 * @author 科技小王子
 * @since 2023-06-10 18:27:25
 */
@Service
public class ChatMessageServiceImpl extends ServiceImpl<ChatMessageMapper, ChatMessage> implements ChatMessageService {

    @Resource
    private ChatConversationService conversationService;

    @Resource
    private ClientCache clientCache;

    @Resource
    private UserService userService;

    @Override
    public PageResult<ChatMessage> pageRel(ChatMessageParam param) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w->{ w.eq(ChatMessage::getFormUserId, param.getToUserId()).eq(ChatMessage::getToUserId,param.getFormUserId()); })
                .or(w->{ w.eq(ChatMessage::getFormUserId, param.getFormUserId()).eq(ChatMessage::getToUserId,param.getToUserId());})
                .orderByAsc(ChatMessage::getCreateTime);

        Page<ChatMessage> chatMessagePage = new Page<>(param.getPage(), param.getLimit());
        Page<ChatMessage> result = baseMapper.selectPage(chatMessagePage, wrapper);
        List<ChatMessage> list = result.getRecords();
        Set<Integer> userIds = new HashSet<>();
        if(param.getFormUserId() != null && param.getToUserId() != null){
            userIds.add(param.getToUserId());
            userIds.add(param.getFormUserId());
        }else {
           list.stream().forEach(d->{
               userIds.add(d.getToUserId());
               userIds.add(d.getFormUserId());
           });
        }
        List<User> users = userService.list(Wrappers.lambdaQuery(User.class).in(User::getUserId, userIds));
        Map<Integer, List<User>> collect = users.stream().collect(Collectors.groupingBy(User::getUserId));
        list.stream().forEach(d->{
            d.setFormUserInfo(collect.get(d.getFormUserId()).get(0));
        });
        return new PageResult<>(list, result.getTotal());
    }

    @Override
    public List<ChatMessage> listRel(ChatMessageParam param) {
        List<ChatMessage> list = baseMapper.selectListRel(param);
        // 排序
        PageParam<ChatMessage, ChatMessageParam> page = new PageParam<>();
        //page.setDefaultOrder("create_time desc");
        return page.sortRecords(list);
    }

    @Override
    public ChatMessage getByIdRel(Integer id) {
        ChatMessageParam param = new ChatMessageParam();
        param.setId(id);
        return param.getOne(baseMapper.selectListRel(param));
    }

    @Override
    public List<ChatMessage> getUnreadMessage(Integer fromUserId, Integer toUserId) {
        return null;
    }

    @Override
    @Transactional
    public boolean sendMessage(ChatMessage message) {
        Integer userId = message.getFormUserId();
        Integer toUserId = message.getToUserId();

        User toUser = userService.getById(toUserId);
        message.setToUserInfo(toUser);
        // 判断双方是否是好友（有消息记录），没有就添加两条记录 后续可以做拉黑什么的处理
        ChatConversation conversation1 = conversationService.getByBothId(userId, toUserId);
        ChatConversation conversation2 = conversationService.getByBothId(toUserId, userId);
        if(conversation1 == null){
            conversation1 = new ChatConversation();
            conversation1.setUserId(Integer.valueOf(userId));
            conversation1.setFriendId(toUserId);
        }
        if(conversation2 == null){
            conversation2 = new ChatConversation();
            conversation2.setUserId(toUserId);
            conversation2.setFriendId(Integer.valueOf(userId));
        }
        String lastContent;
        if(ChatMessageType.IMAGE.getName().equals(message.getType())){
            lastContent = "[图片]";
        } else if (ChatMessageType.VOICE.getName().equals(message.getType())) {
            lastContent = "[语音]";
        }else if (ChatMessageType.CARD.getName().equals(message.getType())) {
            lastContent = "[卡片]";
        }else {
            lastContent = message.getContent();
        }
        conversation1.setContent(lastContent);
        //未读+1
        conversation2.setUnRead(conversation2.getUnRead() + 1);
        conversation2.setContent(lastContent);

        // 发送到接收方
        clientCache.sendUserEvent(message.getToUserId() + "", "message", message);
        // 发送到管理员
        if(!toUser.getUsername().startsWith("wx_")){
            clientCache.sendUserEvent("admin", "message", message);
        }

        this.save(message);
        conversationService.saveOrUpdate(conversation1);
        conversationService.saveOrUpdate(conversation2);
        return  true;
    }

    @Override
    public List<ChatMessage> getFriendMessage(Integer userId1, Integer userId2) {
        LambdaQueryWrapper<ChatMessage> wrapper = new LambdaQueryWrapper<>();
        wrapper.and(w->{ w.eq(ChatMessage::getFormUserId, userId1).eq(ChatMessage::getToUserId,userId2); })
                .or(w->{ w.eq(ChatMessage::getFormUserId, userId2).eq(ChatMessage::getToUserId,userId1);})
                .orderByAsc(ChatMessage::getCreateTime);

        return baseMapper.selectList(wrapper);
    }

}
