package org.springblade.common.notify.message;

import com.aliyun.openservices.ons.api.Action;
import com.aliyun.openservices.ons.api.ConsumeContext;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.MessageListener;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;

/**
 * @author caiyihua
 */
@Slf4j
public abstract class MessageHandler implements MessageListener {
    // 默认失败重试次数
    private static final int MAX_RETRY_TIMES = 3;

    @Override
    public Action consume(Message message, ConsumeContext consumeContext) {

        if (message == null) {
            log.warn("The input message is NULL!!!");
            return Action.CommitMessage;
        }

        try {
            String messageBody = new String(message.getBody(), StandardCharsets.UTF_8);

            if (!message.getTopic().equals(getTopic()) || !message.getTag().equals(getTag())) {
                log.warn(
                        "The input message should not be handled by this handler. The message topic is {}, the message tag is {}; The handler topic is {}, the handler tag is {}.",
                        message.getTopic(), message.getTag(), getTopic(), getTag());
                return Action.CommitMessage;
            }

            boolean flag = handle(messageBody, message.getUserProperties());

            // 如果成功，或者当重试次数超过某个阈值则返回成功.
            if (flag || message.getReconsumeTimes() >= getMaxRetryTimes()) {
                return Action.CommitMessage;
            }

            return Action.ReconsumeLater;
        } catch (Exception e) {
            log.error("consume message error.", e);
            if (message.getReconsumeTimes() >= getMaxRetryTimes()) {
                return Action.CommitMessage;
            }
            return Action.ReconsumeLater;
        }
    }

    /**
     * 处理订阅的消息
     *
     * @param messageBody
     * @param userProperties
     * @return
     */
    public abstract boolean handle(String messageBody, Properties userProperties);

    /**
     * 获取消费者ID
     *
     * @return
     */
    public abstract String getConsumerId();

    /**
     * 获取消息主题
     *
     * @return
     */
    public abstract String getTopic();

    /**
     * 获取消息标签
     *
     * @return
     */
    public abstract String getTag();

    /**
     * 是否广播订阅。注意，同一个CID下的handler返回值必须相同
     *
     * @return
     */
    public boolean isBroadcast() {
        return false;
    }

    /**
     * 消费消息失败后的最大重试次数
     *
     * @return
     */
    public int getMaxRetryTimes() {
        return MAX_RETRY_TIMES;
    }
}
