package org.jeecg.modules.mq;

import static org.jeecg.modules.adweb.enquiry.service.impl.AdwebEnquiryServiceImpl.EnquiryUniqueKey;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import java.io.IOException;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.boot.starter.rabbitmq.core.BaseRabbiMqHandler;
import org.jeecg.boot.starter.rabbitmq.listenter.MqListener;
import org.jeecg.common.annotation.RabbitComponent;
import org.jeecg.modules.adweb.common.service.FeishuService;
import org.jeecg.modules.adweb.common.util.AdwebRedisUtil;
import org.jeecg.modules.adweb.enquiry.dto.EnquiryDTO;
import org.jeecg.modules.adweb.enquiry.service.IAdwebEnquiryService;
import org.jeecg.modules.adweb.site.entity.AdwebSite;
import org.jeecg.modules.adweb.site.service.IAdwebSiteService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.Header;

/**
 * Rabbit MQ - 询盘消息接收
 *
 * @author wfansh
 */
@Slf4j
@RabbitComponent(value = "enquiryReceiver")
public class EnquiryReceiver extends BaseRabbiMqHandler<List<EnquiryDTO>> {

  @Autowired private IAdwebSiteService adwebSiteService;

  @Autowired private IAdwebEnquiryService adwebEnquiryService;

  @Autowired private AdwebRedisUtil adwebRedisUtil;

  @Autowired private FeishuService feishuService;

  @RabbitHandler
  // ackMode需要设置为MANUAL - BaseRabbiMqHandler.onMessage()有channel.basicAck()操作
  @RabbitListener(queues = "site_enquiry", ackMode = "MANUAL")
  public void onMessage(
      List<EnquiryDTO> enquiries,
      Channel channel,
      @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
    super.onMessage(
        enquiries,
        deliveryTag,
        channel,
        new MqListener<List<EnquiryDTO>>() {
          @Override
          public void handler(List<EnquiryDTO> enquiries, Channel channel) {
            // 业务处理
            log.info("收到询盘MQ消息 {}", enquiries);
            for (EnquiryDTO enquiry : enquiries) {
              // 查看发布当前消息的站点是否是 adweb3 平台中绑定的是否是有效站点, 如果不是则直接确认消息，不做业务处理
              AdwebSite adwebSite =
                  adwebSiteService.getOne(
                      new LambdaQueryWrapper<AdwebSite>()
                          .like(AdwebSite::getDomain, enquiry.getSiteHost())
                          .ne(AdwebSite::getStatus, 0));

              if (adwebSite == null) {
                log.error("站点：{} 不是adweb3的有效绑定站点,MQ消息确认失败", enquiry.getSiteHost());
                return;
              }

              // 记录开始时间
              long startTime = System.currentTimeMillis();
              if (adwebRedisUtil.hasKey(EnquiryUniqueKey + enquiry.getSiteHost())) {
                // 消息内容唯一性判断
                List<String> enquiryUniqueIds =
                    (List<String>) adwebRedisUtil.get(EnquiryUniqueKey + enquiry.getSiteHost());
                // 如果该消息内容原数据中已存在，则将该重复消息踢出队列
                if (enquiryUniqueIds.contains(enquiry.getSiteHost() + enquiry.getRecordId())) {
                  log.info("该询盘已经消费过，从队列中清除：{}", enquiry.getRecordId());
                  try {
                    channel.basicAck(deliveryTag, false);
                  } catch (IOException e) {
                    throw new RuntimeException(e);
                  }
                }
              }
              // 记录结束时间
              long endTime = System.currentTimeMillis();

              log.info(
                  "站点：{}，询盘ID：{} 唯一性检测耗时：{} ms",
                  enquiry.getSiteHost(),
                  enquiry.getRecordId(),
                  endTime - startTime);

              // 记录开始时间
              long startTimeEnquiry = System.currentTimeMillis();
              try {
                // 询盘入库
                adwebEnquiryService.addEnquiry(enquiry, enquiry.getPluginName(), adwebSite);
              } catch (Exception e) {
                log.error(
                    "站点：{}，询盘ID：{}，询盘入库异常：{}",
                    enquiry.getSiteHost(),
                    enquiry.getRecordId(),
                    e.getMessage());
                // 拉取询盘失败时，发送告警到飞书
                long endTimeEnquiry = System.currentTimeMillis();
                long diffTime = endTimeEnquiry - startTime;

                // 发送飞书告警
                StringBuilder msg =
                    new StringBuilder(
                        "询盘异常,\n询盘id："
                            + enquiry.getRecordId()
                            + ",\n站点名称："
                            + adwebSite.getName()
                            + ",\n站点域名："
                            + enquiry.getSiteHost()
                            + ",\n来源ip："
                            + enquiry.getFromIp());

                String className = this.getClass().getName();
                String methodName = Thread.currentThread().getStackTrace()[1].getMethodName();

                msg.append(",\n字段异常,存在异常字段：").append(e.getMessage());
                feishuService.sendEnquiryRobot(
                    (float) diffTime / 1000,
                    "MQ消费询盘失败：",
                    className,
                    methodName,
                    String.valueOf(msg));
              }
              // 记录结束时间
              long endTimeEnquiry = System.currentTimeMillis();
              log.info(
                  "站点：{}，询盘ID：{} 询盘入库耗时：{} ms",
                  enquiry.getSiteHost(),
                  enquiry.getRecordId(),
                  startTimeEnquiry - endTimeEnquiry);
            }
          }
        });
  }
}
