package com.bonus.core.pay.common.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.bonus.core.common.constant.LeMqConstant;
import com.bonus.core.common.redis.RedisUtil;
import com.bonus.core.common.utils.JacksonUtil;
import com.bonus.core.common.utils.LogUtil;
import com.bonus.core.common.utils.TenantContextHolder;
import com.bonus.core.order.common.constants.OrderCacheConstants;
//import com.bonus.core.order.mq.MqUtil;
import com.bonus.core.order.mq.MqUtil;
import com.bonus.core.order.mq.constants.OrderMQConstants;
import com.bonus.core.pay.api.dto.UnifyPaySelectDTO;
import com.bonus.core.pay.common.constants.PayStateEnum;
import com.bonus.core.pay.common.constants.TradeTypeEnum;
import com.bonus.core.pay.common.model.TradeRecord;
import com.bonus.core.pay.common.po.PayResultPO;
import com.bonus.core.pay.common.po.PayResultQueryPO;
import com.bonus.core.pay.common.po.RefundResultPO;
import com.bonus.core.pay.common.service.PayTradeService;
import com.bonus.core.pay.common.service.TradeChannelService;
import com.bonus.core.pay.common.service.TradeRecordService;
import com.bonus.core.pay.common.vo.TradeChannelVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class PayTradeServiceImpl implements PayTradeService {
   private static final Logger log = LoggerFactory.getLogger(PayTradeServiceImpl.class);
   @Lazy
   @Resource
   private TradeRecordService tradeRecordService;
   @Lazy
   @Resource
   private TradeChannelService tradeChannelService;

   @Override
   public boolean sendAutoPayResultQuery(UnifyPaySelectDTO paySelectDTO, LocalDateTime startTime, boolean endWithCancel) {
      log.warn("[交易记录结果查询]支付中发送查询 {}", paySelectDTO.getTradeId());
      PayResultQueryPO payResultQueryPO = new PayResultQueryPO();
      payResultQueryPO.setTradeId(paySelectDTO.getTradeId());
      payResultQueryPO.setTraceId(LogUtil.getCurrentTraceId());
      payResultQueryPO.setTenantId(TenantContextHolder.getTenantId());
      payResultQueryPO.setStartTime(startTime);
      payResultQueryPO.setIfAutoDelay(true);
      payResultQueryPO.setEndWithCancel(endWithCancel);
      payResultQueryPO.setPaySelectDTO(paySelectDTO);
      String key = OrderCacheConstants.payQueryTimesKey(paySelectDTO.getTradeId());
      Integer queryTriggerTime = RedisUtil.incr(key, 50L);
      int delay = OrderMQConstants.nextPayQueryDelay(queryTriggerTime);
      LocalDateTime endTime = startTime.plusSeconds((long) OrderMQConstants.PAY_QUERY_MAX_SECOND);
      if (delay != -1 && !endTime.isBefore(LocalDateTime.now())) {
         MqUtil.sendDelay(JacksonUtil.writeValueAsString(payResultQueryPO), LeMqConstant.Topic.PAY_ASYNC_PAY_QUERY, delay * 1000);
         return true;
      } else {
         log.warn("[订单异步保存]订单支付中查询结束 {}, {}", paySelectDTO.getTradeId(), startTime);
         return false;
      }
   }

   @Override
   public void sendResultMq(Long tradeId, int... delayMilliSeconds) {
      TradeRecord tradeRecord = this.tradeRecordService.getTradeRecordById(tradeId);

      try {
         if (TradeTypeEnum.isPayCategory(tradeRecord.getTradeType()) && PayStateEnum.isFinishedState(tradeRecord.getTradeState())) {
            PayResultPO payResultPO = PayResultPO.of(tradeRecord);
            if (ArrayUtil.isNotEmpty(delayMilliSeconds)) {
               MqUtil.sendDelay(JacksonUtil.writeValueAsString(payResultPO), LeMqConstant.Topic.PAY_RESULT, delayMilliSeconds[0]);
            } else {
               MqUtil.sendByTxEnd(JacksonUtil.writeValueAsString(payResultPO), LeMqConstant.Topic.PAY_RESULT);
            }
         } else if (TradeTypeEnum.isRefundCategory(tradeRecord.getTradeType()) && PayStateEnum.isFinishedState(tradeRecord.getTradeState())) {
            List<TradeChannelVO> tradeChannels = this.tradeChannelService.listChannelDetailByTradeId(tradeId);
            RefundResultPO payResultPO = RefundResultPO.of(tradeRecord, tradeChannels);
            if (ArrayUtil.isNotEmpty(delayMilliSeconds)) {
               MqUtil.sendDelay(JacksonUtil.writeValueAsString(payResultPO), LeMqConstant.Topic.REFUND_RESULT, delayMilliSeconds[0]);
            } else {
               MqUtil.sendByTxEnd(JacksonUtil.writeValueAsString(payResultPO), LeMqConstant.Topic.REFUND_RESULT);
            }
         }
      } catch (Exception var6) {
         log.error("[支付结果通知]发送失败", var6);
      }

   }
}
