package com.hzs.third.mqcall.listener;

import com.hzs.common.core.constant.RabbitMqConstants;
import com.hzs.common.core.enums.*;
import com.hzs.common.domain.third.pay.TOnlinePayment;
import com.hzs.common.security.utils.SecurityUtils;
import com.hzs.third.mq.dto.RefundOrderDTO;
import com.hzs.third.pay.service.IPayService;
import com.hzs.third.pay.service.IRefundService;
import com.hzs.third.pay.service.ITOnlinePaymentService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 订单退款处理监听
 */
@Slf4j
@Component
public class PayRefundListener {

    @Autowired
    private ITOnlinePaymentService itOnlinePaymentService;
    @Autowired
    private IPayService iPayService;
    @Autowired
    private IRefundService iRefundService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 此监听只处理在线支付，支付成功，但是订单未成功的处理
     *
     * @param message
     * @param channel
     * @throws Exception
     */
    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = RabbitMqConstants.REFUND_ORDER_EXCHANGE, type = "topic"),
            value = @Queue(value = RabbitMqConstants.REFUND_ORDER_QUEUE, durable = "true", autoDelete = "false"),
            key = RabbitMqConstants.REFUND_ORDER_KEY))
    @RabbitHandler
    public void onMessage(Message<RefundOrderDTO> message, Channel channel) throws Exception {
        // 手动应答
        Long deliveryTag = (Long) message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
        channel.basicAck(deliveryTag, false);

        RefundOrderDTO refundOrderDTO = message.getPayload();
        log.info("订单退款MQ处理. 参数：{}", refundOrderDTO);

        // 防止MQ推送比实际更新数据库快，此处停1.5秒再处理
        Thread.sleep(1500);

        // 重试次数
        int retryNum = null != refundOrderDTO.getRetryNum() ? refundOrderDTO.getRetryNum() : 0;
        if (retryNum > 2) {
            log.error("订单退款MQ处理. 订单退款已重试3次，仍未成功，不进行再次重试");
            return;
        }
        // 支付会员ID
        Long pkMember = refundOrderDTO.getPkMember();
        // 支付订单编号
        String orderCode = refundOrderDTO.getOrderCode();
        // 支付业务类型
        Integer payBusinessType = refundOrderDTO.getPayBusinessType();

        // 业务类型（默认为会员订单）
        EPayBusinessType eBusinessType = EPayBusinessType.MEMBER_ORDER;
        if (null != payBusinessType) {
            // 传入支付业务类型不为空，则进行转换
            EPayBusinessType ePayBusinessType = EPayBusinessType.getEnumByValue(payBusinessType);
            if (null != ePayBusinessType) {
                eBusinessType = ePayBusinessType;
            }
        }

        // 校验在线支付信息是否可以进行退款
        TOnlinePayment tOnlinePayment = itOnlinePaymentService.queryByBusiness(eBusinessType.getValue(), orderCode, null);
        if (null == tOnlinePayment) {
            // 在线支付信息不存在
            log.error("订单退款MQ处理. 在线支付信息不存在");
            return;
        }
        if (EPayStatus.PAID.getValue() == tOnlinePayment.getPayStatus()
                && ECallbackStatus.FAIL.getValue() == tOnlinePayment.getCallbackStatus()) {
            // 已支付 并且 回调业务失败，可以进行退款

            // 业务重试次数
            int businessRetryNum = null != refundOrderDTO.getBusinessRetryNum() ? refundOrderDTO.getBusinessRetryNum() : 0;
            if (businessRetryNum > 2) {
                log.error("订单退款MQ处理. 会员订单业务已重试3次，仍未成功，不进行再次重试。开始进行退款");

                // 退款处理
                String str = this.handleRefund(tOnlinePayment, eBusinessType, orderCode, pkMember);
                if (null == str) {
                    log.info("退款MQ处理退款成功");
                    return;
                } else {
                    log.error("退款MQ处理. 申请三方支付退款失败：{}", str);
                }

                // 退款失败，重试次数+1，推送MQ
                refundOrderDTO.setRetryNum(++retryNum);
                rabbitTemplate.convertAndSend(RabbitMqConstants.REFUND_ORDER_EXCHANGE, RabbitMqConstants.REFUND_ORDER_KEY, refundOrderDTO);
                return;
            }

            // 会员订单，缓冲2秒后，进行重试
            Thread.sleep(2000);

            tOnlinePayment.setPkModified(SecurityUtils.getUserId());
            tOnlinePayment.setModifiedTime(new Date());
            // 业务处理重试
            if (iPayService.retryHandle(tOnlinePayment, false)) {
                // 业务处理重试成功，直接结束
                return;
            }

            // 业务处理重试失败，次数+1，继续推送MQ
            refundOrderDTO.setBusinessRetryNum(++businessRetryNum);
            rabbitTemplate.convertAndSend(RabbitMqConstants.REFUND_ORDER_EXCHANGE, RabbitMqConstants.REFUND_ORDER_KEY, refundOrderDTO);
            return;
        }
        log.info("订单退款MQ处理. 订单未支付或业务已经处理成功");
    }

    /**
     * 处理退款
     *
     * @param tOnlinePayment 支付信息
     * @param eBusinessType  支付业务类型
     * @param orderCode      订单编号
     * @param pkMember       会员ID
     * @return
     */
    private String handleRefund(TOnlinePayment tOnlinePayment, EPayBusinessType eBusinessType, String orderCode, Long pkMember) {
        String str = null;

        // 订单存在并且没有支付成功，代表着钱收到了，但是单没有下成，所以需要进行退款
        switch (EPayChannel.getEnumByValue(tOnlinePayment.getPayChannel())) {
            case HUIFU:
                // 新汇付
//                str = iRefundService.huifuRefundHandle(tOnlinePayment);
                break;
            default:
        }
        return str;
    }

}
