package com.red.circle.mq.rocket.business.service;

import com.red.circle.component.mq.MessageEvent;
import com.red.circle.component.mq.config.RocketMqFailMessage;
import com.red.circle.component.mq.config.RocketMqSenderFailService;
import com.red.circle.component.mq.service.FixedTopic;
import com.red.circle.component.mq.service.ProducerMessage;
import com.red.circle.component.mq.service.SendCallback;
import com.red.circle.tool.core.date.DateUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * 安全的 MQ 发送服务.
 *
 * @author Leo
 */
@Slf4j
@Service
public class MessageSenderService {

  private final ManagedRocketMQProducer managedRocketMQProducer;
  private final RocketMqSenderFailService rocketMqSenderFailService;

  public MessageSenderService(
      ManagedRocketMQProducer managedRocketMQProducer,
      @Qualifier("rocketMqSenderFailServiceRedisImpl")
      RocketMqSenderFailService rocketMqSenderFailService) {
    this.managedRocketMQProducer = managedRocketMQProducer;
    this.rocketMqSenderFailService = rocketMqSenderFailService;
  }

  public void sendEventMessage(final MessageEvent event) {
    this.sendEventMessage(event, new SendCallback() {
      @Override
      public void onSuccess(String messageId, ProducerMessage message) {

      }

      @Override
      public void onFail(Throwable throwable) {
        log.error("SafeSenderService.sendEventMessage onFail: {},{}", 
            throwable.getMessage(), event.toJson());
        rocketMqSenderFailService.add(RocketMqFailMessage.builder()
            .id(event.getConsumeId())
            .topic(event.getTopic())
            .tag(event.getTag())
            .errorMsg(throwable.getMessage())
            .body(event.getBody())
            .startDeliverTime(event.getStartDeliverTime())
            .process(Boolean.FALSE)
            .createTime(DateUtils.now())
            .updateTime(DateUtils.now())
            .expiredTime(DateUtils.nowPlusDays(7))
            .build());
      }
    });
  }

  public void sendEventMessage(MessageEvent event, SendCallback sendCallback) {
    checkEvent(event);
    checkSetDefaultTopic(event);
    
    ProducerMessage message = convertMessage(event);
    managedRocketMQProducer.sendAsync(message, sendCallback);
  }

  private void checkSetDefaultTopic(MessageEvent event) {
    if (!StringUtils.isNotBlank(event.getTopic())) {
      if (event.checkStartDeliverTimeMessage()) {
        event.setTopic(FixedTopic.RC_DEFAULT_APP_DELAYED.getTopic());
      } else if (event.checkOrderMessage()) {
        event.setTopic(FixedTopic.RC_DEFAULT_APP_ORDER.getTopic());
      } else {
        event.setTopic(FixedTopic.RC_DEFAULT_APP_ORDINARY.getTopic());
      }
    }
  }

  private ProducerMessage convertMessage(MessageEvent event) {
    return ProducerMessage.builder()
        .topic(event.getTopic())
        .tag(event.getTag())
        .messageGroup(event.getMessageGroup())
        .keys(new String[]{event.messageKey()})
        .body(event.toBytes(StandardCharsets.UTF_8))
        .deliveryTimestamp(event.checkStartDeliverTimeMessage() ? event.getStartDeliverTime() : null)
        .build();
  }

  private void checkEvent(MessageEvent event) {
    if (Objects.isNull(event)) {
      throw new IllegalArgumentException("SafeSenderService.sendObject event is null.");
    }
    if (StringUtils.isBlank(event.getTag())) {
      throw new IllegalArgumentException("SafeSenderService.sendObject tag isBlank.");
    }
    if (StringUtils.isBlank(event.getBody())) {
      throw new IllegalArgumentException("SafeSenderService.sendObject body isBlank.");
    }
  }
}
