
package com.tmerclub.cloud.order.task;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.tmerclub.cloud.api.feign.SearchOrderRefundTaskFeignClient;
import com.tmerclub.cloud.common.constant.PayType;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.order.constant.ReturnProcessStatusEnum;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.rocketmq.config.RocketMqConstant;
import com.tmerclub.cloud.order.manager.MongoOrderRefundManager;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 退款订单定时任务
 *
 * @author tmerclub
 */
@Component
public class OrderRefundTask {

    @DubboReference
    private SearchOrderRefundTaskFeignClient searchOrderRefundTaskFeignClient;
    @Autowired
    private MongoOrderRefundManager orderRefundManager;
    @Autowired
    private RocketMQTemplate orderRefundUpdateRefundStatusMqTemplate;

    /**
     * 取消申请超时的订单，无论该超时订单处于任何状态
     */
    @XxlJob("cancelWhenTimeOut")
    public void cancelWhenTimeOut() {
        XxlJobHelper.log("取消申请超时的订单，无论该超时订单处于任何状态");

        ServerResponseEntity<Object> serverResponseEntity = searchOrderRefundTaskFeignClient.cancelWhenTimeOut();
        if (!serverResponseEntity.isSuccess()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }
    }

    /**
     * 退款临近超时提醒,每12小时执行发送一次的提醒
     */
    @XxlJob("pressProximityTimeOutOrder")
    public void pressProximityTimeOutOrder() {
        XxlJobHelper.log("退款临近超时提醒,每12小时执行发送一次的提醒");
        ServerResponseEntity<Object> serverResponseEntity = searchOrderRefundTaskFeignClient.pressProximityTimeOutOrder();
        if (!serverResponseEntity.isSuccess()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }
    }

    /**
     * 发放退款定时任务，给十分钟之前还没有收到退款回调的订单重新发放退款
     * 一分钟执行一次
     */
    @XxlJob("refundRequest")
    public void refundRequest() {
        XxlJobHelper.log("发放退款定时任务开始");
        ServerResponseEntity<Object> serverResponseEntity = searchOrderRefundTaskFeignClient.refundRequest();
        if (!serverResponseEntity.isSuccess()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }
    }

    /**
     * 因为支付宝电脑支付订单全额退款成功是没有退款回调的，所以需要该定时任务定时执行
     * 调用主动查单 查十秒钟前,两小时内还没回调的支付宝电脑支付订单退款的状态
     * 一分钟执行一次
     */
    @XxlJob("updateAliPayRefundStatus")
    public void updateAliPayRefundStatus() {
        XxlJobHelper.log("支付宝退款订单查单开始");
        Date decisionStartTime = DateUtil.offsetHour(new Date(), -2).toJdkDate();
        Date decisionEndTime = DateUtil.offsetSecond(new Date(), -10).toJdkDate();
        List<Long> refundIds = orderRefundManager.listShouldUpdateRefund(decisionStartTime, decisionEndTime, PayType.ALIPAY.value(), ReturnProcessStatusEnum.PROCESSING.value());
        if (CollUtil.isNotEmpty(refundIds)) {
            // 发送消息，支付宝电脑支付回调
            SendStatus sendStatus = orderRefundUpdateRefundStatusMqTemplate.syncSend(RocketMqConstant.ORDER_REFUND_UPDATE_REFUND_STATUS, new GenericMessage<>(refundIds)).getSendStatus();
            if (!Objects.equals(sendStatus, SendStatus.SEND_OK)) {
                // 消息发不出去就抛异常，因为定时任务回调会有多次，几乎不可能每次都无法发送出去，发的出去无所谓因为接口是幂等的
                throw new LuckException(ResponseEnum.EXCEPTION);
            }
        }
    }

    /**
     * 执行平台介入超时处理，超时则默认平台不同意退款
     */
    @XxlJob("refundInterventionTimeOut")
    public void cancelRefundInterventionTimeOut() {
        XxlJobHelper.log("执行平台介入超时处理，超时默认平台不同意退款");
        ServerResponseEntity<Object> serverResponseEntity = searchOrderRefundTaskFeignClient.cancelRefundInterventionTimeOut();
        if (!serverResponseEntity.isSuccess()) {
            throw new LuckException(serverResponseEntity.getMsg());
        }
    }
}
