package com.union.ai.api.client.consumer;

import com.alibaba.fastjson.JSON;
import com.union.ai.api.client.service.LogWriterService;
import com.union.ai.api.common.consts.RocketMqConsts;
import com.union.ai.api.dao.mapper.ApiLogMapper;
import com.union.ai.api.dao.model.ApiLog;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * Author: xingxin.jing
 * Date: 2019/4/13
 * Time: 上午10:15
 */
@Slf4j
@Service
public class LogConsumer {

    @Value("${name.srv.addr}")
    private String nameSrvAdd;

    @Autowired
    private ApiLogMapper apiLogMapper;

    private DefaultMQPushConsumer consumer;

    @Autowired
    private LogWriterService logWriterService;


    @PostConstruct
    public void init() {
        try {
            consumer = new DefaultMQPushConsumer(RocketMqConsts.AI_CLIENT_MQ_GROUP);
            consumer.setNamesrvAddr(nameSrvAdd);
            //集群消费
            consumer.setMessageModel(MessageModel.CLUSTERING);
            consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_FIRST_OFFSET);
            consumer.subscribe(RocketMqConsts.AI_MQ_TOPIC, "*");
            consumer.setVipChannelEnabled(false);
            consumer.registerMessageListener(new MessageListenerConcurrently() {
                @Override
                public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> list, ConsumeConcurrentlyContext consumeConcurrentlyContext) {
                    String body = null;
                    String msgId = null;
                    for (MessageExt messageExt : list) {
                        try {
                            msgId = messageExt.getMsgId();
                            log.info("消费日志消息开始，msgId={}", msgId);
                            body = new String(messageExt.getBody(), RemotingHelper.DEFAULT_CHARSET);
                            ApiLog apiLog = JSON.parseObject(body, ApiLog.class);
                            //log.info("apiLog-json:", JSON.toJSONString(apiLog));

                            Integer appId = apiLog.getAppId();
                            if (appId == null) {
                                log.warn("appId 为空，不处理");
                                return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                            }
                            String url = logWriterService.synWriteLog(appId.toString(), apiLog.getParams());
                            apiLog.setParams(null);
                            apiLog.setImgUrl(url);
                            apiLogMapper.insert(apiLog);
                        } catch (Exception e) {
                            log.error("日志数据入库失败,msgId=" + msgId +",body=" + body, e);
                            return ConsumeConcurrentlyStatus.RECONSUME_LATER;
                        }
                    }
                    return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
                }
            });
            consumer.start();
            log.info("rocketmq启动成功nameSrv：" + nameSrvAdd);
        } catch (Exception e) {
            log.error("日志消费MQ启动失败", e);
            throw new RuntimeException("日志消费MQ启动失败");
        }
    }

    @PreDestroy
    public void shutdown() {
        log.info("进程即将停止");
        if (consumer != null) {
            consumer.shutdown();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("sleep error", e);
            }
            logWriterService.destroy();
        }
    }
}
