package org.springblade.common.notify.rocketmq.consumer;

import com.aliyun.openservices.ons.api.PropertyKeyConst;
import com.aliyun.openservices.ons.api.PropertyValueConst;
import com.aliyun.openservices.shade.com.alibaba.rocketmq.common.protocol.heartbeat.MessageModel;
import org.springblade.common.notify.constant.NotifyErrorConstants;
import org.springblade.common.notify.message.MessageHandlerAnnotation;
import com.wn.common.validator.Validator;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 统一初始化阿里MQ消息消费者
 *
 * @author caiyihua
 */
@Slf4j
@Configuration
@ConditionalOnProperty(name = "ali.mq.consumer.support.flag", havingValue = "true", matchIfMissing = false)
public class RocketConsumerInitProcessor implements ApplicationListener<ContextRefreshedEvent> {
    @Value("${ali.mq.new.version:false}")
    @Setter
    private Boolean newVersion;
    @Value("${ali.mq.namesrv.addr:http://onsaddr.mq-internet-access.mq-internet.aliyuncs.com:80}")
    @Setter
    private String nameServer;
    @Value("${ali.mq.type:aliyun}")
    @Setter
    private String mqType;
    @Value("${ali.mq.access.key}")
    @Setter
    private String accessKey;
    @Value("${ali.mq.secret.key}")
    @Setter
    private String secretKey;
    @Value("${ali.mq.consume.thread.nums:20}")
    @Setter
    private Integer consumeThreadNums;
    @Setter
    private Map<String, List<MqMessageHandlerHolder>> handlerHolderMap;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        Map<String, Object> beans = contextRefreshedEvent.getApplicationContext()
                .getBeansWithAnnotation(MessageHandlerAnnotation.class);
        log.info("There are {} message handlers were found!", beans.size());
        handlerHolderMap = new ConcurrentHashMap<>();
        for (Object bean : beans.values()) {
            if (bean instanceof MqMessageHandler) {
                log.info("The message handler class name is: {}", bean.getClass().getName());
                String consumerId = ((MqMessageHandler) bean).getConsumerId();
                String topic = ((MqMessageHandler) bean).getTopic();
                String tag = ((MqMessageHandler) bean).getTag();
                boolean isBroadcast = ((MqMessageHandler) bean).isBroadcast();
                int maxRetryTimes = ((MqMessageHandler) bean).getMaxRetryTimes();
                MqMessageHandlerHolder mqMessageHandlerHolder = new MqMessageHandlerHolder(consumerId, topic, tag,
                        isBroadcast, maxRetryTimes,
                        (MqMessageHandler) bean);
                List<MqMessageHandlerHolder> handlerHolderList = handlerHolderMap.get(consumerId);
                if (handlerHolderList == null) {
                    handlerHolderList = new ArrayList<>();
                    handlerHolderMap.put(consumerId, handlerHolderList);
                }
                handlerHolderList.add(mqMessageHandlerHolder);
            }
        }

        if (handlerHolderMap.isEmpty()) {
            log.info("There is no any message handler found, just ignore the event!");
            return;
        }

        start();
    }

    /**
     * 订阅消息
     */
    public void start() {
        Validator.isTrueParameter(!CollectionUtils.isEmpty(handlerHolderMap),
                NotifyErrorConstants.MQ_MESSAGE_PARMETER_ERROR);
        for (String consumerId : handlerHolderMap.keySet()) {
            List<MqMessageHandlerHolder> handlerHolderList = handlerHolderMap.get(consumerId);

            if (CollectionUtils.isEmpty(handlerHolderList)) {
                log.warn("There is no any message handler for consumer ID {}, just ignore it!", consumerId);
                continue;
            }

            Properties properties = new Properties();
            // AccessKey 阿里云身份验证，在阿里云服务器管理控制台创建
            properties.put(PropertyKeyConst.AccessKey, accessKey);
            // SecretKey 阿里云身份验证，在阿里云服务器管理控制台创建
            properties.put(PropertyKeyConst.SecretKey, secretKey);
            properties.put(PropertyKeyConst.MessageModel, MessageModel.CLUSTERING);
            String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
            properties.put(PropertyKeyConst.InstanceName, uuid);
            properties.put(PropertyKeyConst.ConsumeThreadNums, consumeThreadNums);
            properties.put(PropertyKeyConst.MQType, mqType);
            if (newVersion) {
                // 您在控制台创建的 Group ID
                properties.put(PropertyKeyConst.GROUP_ID, consumerId);
                // 设置 TCP 接入域名（此处以公共云生产环境为例）
                properties.put(PropertyKeyConst.NAMESRV_ADDR, nameServer);
            } else {
                // 您在控制台创建的 Consumer ID
                properties.put(PropertyKeyConst.ConsumerId, consumerId);
                // 设置 TCP 接入域名（此处以公共云生产环境为例）
                properties.put(PropertyKeyConst.ONSAddr,
                        "http://onsaddr-internet.aliyun.com/rocketmq/nsaddr4client-internet");
            }
            // 集群订阅方式 (默认)
            // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.CLUSTERING);
            // 广播订阅方式
            if (handlerHolderList.get(0).isBroadcast()) {
                properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING);
            }
            for (MqMessageHandlerHolder mqMessageHandlerHolder : handlerHolderList) {
                ConsumerProxy consumerProxy = ConsumerProxyFactory.makeConsumerProxy(mqType);
                consumerProxy.startup(properties, mqMessageHandlerHolder);
            }
        }
    }
}
