package com.webchat.service.listener;

import com.webchat.common.enums.ChatMessageTypeEnum;
import com.webchat.common.util.JsonUtil;
import com.webchat.controller.client.ChatWebSocket;
import com.webchat.domain.vo.response.UserBaseResponseInfoVO;
import com.webchat.domain.vo.response.mess.ChatMessageResponseVO;
import com.webchat.domain.vo.response.mess.PublicAccountArticleMessageVO;
import com.webchat.domain.vo.response.publicaccount.ArticleBaseResponseVO;
import com.webchat.service.FriendService;
import com.webchat.service.UserService;
import com.webchat.service.publicaccount.ArticleService;
import com.webchat.service.queue.dto.ArticleDelayConsumeMessageDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.Session;
import java.util.Set;

@Slf4j
@Component
public class RedisPushMessageListener implements MessageListener {

    @Autowired
    private FriendService friendService;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private UserService userService;

    private final RedisTemplate redisTemplate;

    public RedisPushMessageListener(@Qualifier("redisTemplate") RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Override
    public void onMessage(Message message, byte[] bytes) {
        String channel = (String) redisTemplate.getStringSerializer().deserialize(message.getChannel());
        String messageStr = (String) redisTemplate.getValueSerializer().deserialize(message.getBody());
        log.info("redis message listener ======> channel:{}, message:{}", channel, messageStr);
        // 订阅到公众号实时推文消息，推文逻辑
        this.doPushPublicAccountArticle(messageStr);
    }

    /**
     * 公众号推文，支持分布式websocket
     *
     * @param messageStr
     */
    private void doPushPublicAccountArticle(String messageStr) {
        // 1. 消息反序列化
        ArticleDelayConsumeMessageDTO data = JsonUtil.fromJson(messageStr, ArticleDelayConsumeMessageDTO.class);
        if (data == null) {
            return;
        }
        // 2. 拿公众号
        String publicAccount = data.getPublicAccount();
        UserBaseResponseInfoVO publicAccountUser = userService.getUserInfoByUserId(publicAccount);
        // 3. 查询推送文章信息
        ArticleBaseResponseVO articleBaseResponse = articleService.getArticleDetailFromCache(data.getArticleId());
        // 4. 走redis拿公众号下所有订阅用户
        Set<String> subscribeUsers = friendService.listSubscribeFriendIds(publicAccount);
        if (CollectionUtils.isEmpty(subscribeUsers)) {
            return;
        }
        // 5. 处理在线场景推文
        for (String userId : subscribeUsers) {
            // 5.1 获取公众号所有订阅且在线用户（需要实时推文）
            ChatWebSocket ws = ChatWebSocket.clients.get(userId);
            if (ws == null) {
                continue;
            }
            Session session = ws.getSession();
            if (session == null || !session.isOpen()) {
                continue;
            }
            // 5.2 构造文章卡片
            PublicAccountArticleMessageVO publicAccountArticleMessageDTO = new PublicAccountArticleMessageVO();
            publicAccountArticleMessageDTO.setArticleId(articleBaseResponse.getId());
            publicAccountArticleMessageDTO.setCover(articleBaseResponse.getCover());
            publicAccountArticleMessageDTO.setDescription(articleBaseResponse.getDescription());
            publicAccountArticleMessageDTO.setTitle(articleBaseResponse.getTitle());
            publicAccountArticleMessageDTO.setTime(System.currentTimeMillis());
            publicAccountArticleMessageDTO.setRedirectUrl(articleBaseResponse.getRedirectUrl());

            ChatMessageResponseVO publicAccountArticleMessage = new ChatMessageResponseVO();
            publicAccountArticleMessage.setType(ChatMessageTypeEnum.PUBLIC_ACCOUNT_ARTICLE.getType());
            publicAccountArticleMessage.setSenderId(publicAccount);
            publicAccountArticleMessage.setSender(publicAccountUser);
            publicAccountArticleMessage.setReceiverId(userId);
            publicAccountArticleMessage.setMessage(JsonUtil.toJsonString(publicAccountArticleMessageDTO));
            // 5.3 实时推文
            session.getAsyncRemote().sendText(JsonUtil.toJsonString(publicAccountArticleMessage));
        }
    }
}
