package com.seer.teach.pay.app.notify.service.impl;


import com.seer.teach.common.enums.AfterSaleStatusEnum;
import com.seer.teach.common.enums.pay.PayNotifyTypeEnum;
import com.seer.teach.common.enums.pay.PayOrderSourceEnum;
import com.seer.teach.common.enums.pay.PayStatusEnum;
import com.seer.teach.common.enums.pay.RefundTypeEnum;
import com.seer.teach.mall.api.MallAfterSaleApi;
import com.seer.teach.mall.api.MallOrderApi;
import com.seer.teach.mall.api.req.AfterSaleRefundNotifyReq;
import com.seer.teach.mall.api.req.OrderPayNotifyReq;
import com.seer.teach.mall.api.req.OrderRefundNotifyReq;
import com.seer.teach.pay.app.merchant.service.IMerchantEarningsService;
import com.seer.teach.pay.app.notify.service.AbstractOrderPayNotifyHandler;
import com.seer.teach.pay.entity.PayNotifyTaskEntity;
import com.seer.teach.pay.entity.PayOrderEntity;
import com.seer.teach.pay.entity.RefundOrderEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * 商城订单支付处理策略
 */
@Slf4j
@Component
public class MallOrderPaymentNotifyHandler extends AbstractOrderPayNotifyHandler {

    @Autowired
    private MallOrderApi mallOrderApi;

    @Autowired
    private MallAfterSaleApi mallAfterSaleApi;

    @Autowired
    private IMerchantEarningsService merchantEarningsService;

    @Override
    public void orderPayAfterSuccess(PayOrderEntity payOrder) {
        log.info("开始处理商城订单支付成功，支付订单：{}", payOrder);
        // 创建通知任务
        PayNotifyTaskEntity notifyTask = createPayNotifyTask(payOrder, PayNotifyTypeEnum.MALL_PAY_SUCCESS.getCode());

        // 记录通知日志
        executeNotifyWithLog(notifyTask, PayNotifyTypeEnum.MALL_PAY_SUCCESS, () -> {
            OrderPayNotifyReq orderPayNotifyReq = createOrderStatusUpdateReqForPaySuccess(payOrder);
            boolean notifyResult = mallOrderApi.orderPayAfterSuccessNotify(orderPayNotifyReq);
            if (notifyResult) {
                log.info("开始处理商家收益结算，订单号：{}", payOrder.getMerchantOrderSn());
                merchantEarningsService.settleMerchantEarnings(payOrder);
                log.info("商家收益结算完成，订单号：{}", payOrder.getMerchantOrderSn());
            }
            return true;
        });
    }

    @Override
    public void orderPayAfterFail(PayOrderEntity payOrder) {
        log.info("开始处理商城订单支付失败，订单号：{}", payOrder.getOrderSn());
        // 创建通知任务
        PayNotifyTaskEntity notifyTask = createPayNotifyTask(payOrder, PayNotifyTypeEnum.MALL_PAY_FAIL.getCode());

        // 记录通知日志
        executeNotifyWithLog(notifyTask, PayNotifyTypeEnum.MALL_PAY_FAIL, () -> {
            OrderPayNotifyReq orderPayNotifyReq = createOrderStatusUpdateReqForPayFail(payOrder);
            log.info("创建订单支付失败状态更新请求完成，请求参数：{}", orderPayNotifyReq);
            return mallOrderApi.orderPayAfterFailNotify(orderPayNotifyReq);
        });


    }

    @Override
    public void orderRefundAfterSuccess(RefundOrderEntity refundOrder) {
        log.info("开始处理商城订单退款成功，退款订单：{}", refundOrder);
        PayNotifyTaskEntity notifyTask = createRefundNotifyTask(refundOrder, PayNotifyTypeEnum.MALL_REFUND_SUCCESS.getCode());
        executeNotifyWithLog(notifyTask, PayNotifyTypeEnum.MALL_PAY_FAIL, () -> {
            // 判断是售后退款还是订单取消退款
            boolean mallOrderUpdateResult = false;
            if (isAfterSaleRefund(refundOrder)) {
                // 售后退款处理
                AfterSaleRefundNotifyReq afterSaleRefundNotifyReq = createOrderStatusUpdateReqForRefundSuccess(refundOrder);

                mallOrderUpdateResult = mallAfterSaleApi.orderRefundAfterSuccessNotify(afterSaleRefundNotifyReq);

            } else if (RefundTypeEnum.ORDER_CANCEL.getCode().equals(refundOrder.getRefundType())) {
                // 订单取消退款处理
                OrderRefundNotifyReq orderRefundNotifyReq = createOrderRefundNotifyReqForRefundSuccess(refundOrder);
                // 记录通知日志
                mallOrderUpdateResult = mallOrderApi.cancelOrderRefundAfterSuccessNotify(orderRefundNotifyReq);
            }
            // 处理商家收益退款
            if (mallOrderUpdateResult) {
                merchantEarningsService.refundMerchantEarnings(refundOrder);
                log.info("商家收益退款处理完成，退款订单号：{}", refundOrder.getRefundSn());
            } else {
                log.error("商家收益退款处理失败，订单号：{}", refundOrder.getMerchantOrderSn());
            }
            return mallOrderUpdateResult;
        });
    }

    @Override
    public void orderRefundAfterFail(RefundOrderEntity refundOrder) {
        log.info("开始处理商城订单退款失败，退款订单：{}", refundOrder);
        PayNotifyTaskEntity notifyTask = createRefundNotifyTask(refundOrder, PayNotifyTypeEnum.MALL_REFUND_FAIL.getCode());
        executeNotifyWithLog(notifyTask, PayNotifyTypeEnum.MALL_PAY_FAIL, () -> {
            // 判断是售后退款还是订单取消退款
            boolean mallOrderUpdateResult = false;
            if (isAfterSaleRefund(refundOrder)) {
                // 售后退款处理
                AfterSaleRefundNotifyReq afterSaleRefundNotifyReq = createOrderStatusUpdateReqForRefundFail(refundOrder);
                mallOrderUpdateResult = mallAfterSaleApi.orderRefundAfterFailNotify(afterSaleRefundNotifyReq);
            } else if (RefundTypeEnum.ORDER_CANCEL.getCode().equals(refundOrder.getRefundType())) {
                // 订单取消退款处理
                OrderRefundNotifyReq orderRefundNotifyReq = createOrderRefundNotifyReqForRefundFail(refundOrder);
                // 记录通知日志
                mallOrderUpdateResult = mallOrderApi.cancelOrderRefundAfterFailNotify(orderRefundNotifyReq);
            }
            // 处理商家收益退款
            if (mallOrderUpdateResult) {
                merchantEarningsService.refundMerchantEarnings(refundOrder);
                log.info("商家收益退款处理完成，退款订单号：{}", refundOrder.getRefundSn());
            } else {
                log.error("商家收益退款处理失败，订单号：{}", refundOrder.getMerchantOrderSn());
            }
            return mallOrderUpdateResult;
        });
    }

    @Override
    public PayOrderSourceEnum getOrderSource() {
        return PayOrderSourceEnum.MALL_ORDER_PAYMENT;
    }

    /**
     * 判断是否为售后退款
     *
     * @param refundOrder 退款订单
     * @return true-售后退款，false-订单取消退款
     */
    private boolean isAfterSaleRefund(RefundOrderEntity refundOrder) {
        if (refundOrder.getRefundType() != null) {
            return RefundTypeEnum.AFTER_SALE.getCode().equals(refundOrder.getRefundType());
        }
        return false;
    }

    /**
     * 创建支付成功时的订单状态更新请求
     *
     * @param payOrder 支付订单
     * @return 订单状态更新请求
     */
    private OrderPayNotifyReq createOrderStatusUpdateReqForPaySuccess(PayOrderEntity payOrder) {
        log.info("开始创建支付成功时的订单状态更新请求，支付订单：{}", payOrder);
        OrderPayNotifyReq orderPayNotifyReq = new OrderPayNotifyReq();
        orderPayNotifyReq.setOrderSn(payOrder.getMerchantOrderSn());
        orderPayNotifyReq.setPayStatus(PayStatusEnum.SUCCESS.getCode());
        orderPayNotifyReq.setPayOrderId(payOrder.getId());
        orderPayNotifyReq.setPayChannelCode(payOrder.getChannelCode());
        orderPayNotifyReq.setPayTime(payOrder.getSuccessTime());
        log.info("创建支付成功时的订单状态更新请求完成，请求参数：{}", orderPayNotifyReq);
        return orderPayNotifyReq;
    }

    /**
     * 创建支付失败时的订单状态更新请求
     *
     * @param payOrder 支付订单
     * @return 订单状态更新请求
     */
    private OrderPayNotifyReq createOrderStatusUpdateReqForPayFail(PayOrderEntity payOrder) {
        log.info("开始创建支付失败时的订单状态更新请求，支付订单：{}", payOrder);
        OrderPayNotifyReq orderPayNotifyReq = new OrderPayNotifyReq();
        orderPayNotifyReq.setOrderSn(payOrder.getMerchantOrderSn());
        orderPayNotifyReq.setPayStatus(PayStatusEnum.PAY_FAILED.getCode());
        orderPayNotifyReq.setPayOrderId(payOrder.getId());
        orderPayNotifyReq.setPayChannelCode(payOrder.getChannelCode());
        orderPayNotifyReq.setPayTime(LocalDateTime.now());
        log.info("创建支付失败时的订单状态更新请求完成，请求参数：{}", orderPayNotifyReq);
        return orderPayNotifyReq;
    }

    /**
     * 创建退款成功时的订单状态更新请求（售后）
     *
     * @param refundOrder 退款订单
     * @return 订单状态更新请求
     */
    private AfterSaleRefundNotifyReq createOrderStatusUpdateReqForRefundSuccess(RefundOrderEntity refundOrder) {
        log.info("开始创建退款成功时的订单状态更新请求，退款订单：{}", refundOrder);
        AfterSaleRefundNotifyReq orderPayNotifyReq = new AfterSaleRefundNotifyReq();
        orderPayNotifyReq.setAfterSaleSn(refundOrder.getMerchantRefundSn());
        orderPayNotifyReq.setAfterSaleStatus(AfterSaleStatusEnum.COMPLETE.getStatus());
        log.info("创建退款成功时的订单状态更新请求完成，请求参数：{}", orderPayNotifyReq);
        return orderPayNotifyReq;
    }

    /**
     * 创建退款失败时的订单状态更新请求（售后）
     *
     * @param refundOrder 退款订单
     * @return 订单状态更新请求
     */
    private AfterSaleRefundNotifyReq createOrderStatusUpdateReqForRefundFail(RefundOrderEntity refundOrder) {
        log.info("开始创建退款失败时的订单状态更新请求，退款订单：{}", refundOrder);
        AfterSaleRefundNotifyReq orderPayNotifyReq = new AfterSaleRefundNotifyReq();
        orderPayNotifyReq.setAfterSaleSn(refundOrder.getMerchantRefundSn());
        orderPayNotifyReq.setAfterSaleStatus(AfterSaleStatusEnum.REFUND_FAILED.getStatus());
        log.info("创建退款失败时的订单状态更新请求完成，请求参数：{}", orderPayNotifyReq);
        return orderPayNotifyReq;
    }

    /**
     * 创建退款成功时的订单状态更新请求（订单取消）
     *
     * @param refundOrder 退款订单
     * @return 订单状态更新请求
     */
    private OrderRefundNotifyReq createOrderRefundNotifyReqForRefundSuccess(RefundOrderEntity refundOrder) {
        log.info("开始创建订单取消退款成功时的订单状态更新请求，退款订单：{}", refundOrder);
        OrderRefundNotifyReq orderRefundNotifyReq = new OrderRefundNotifyReq();
        orderRefundNotifyReq.setOrderSn(refundOrder.getMerchantOrderSn());
        orderRefundNotifyReq.setRefundStatus("SUCCESS");
        orderRefundNotifyReq.setRefundSn(refundOrder.getRefundSn());
        log.info("创建订单取消退款成功时的订单状态更新请求完成，请求参数：{}", orderRefundNotifyReq);
        return orderRefundNotifyReq;
    }

    /**
     * 创建退款失败时的订单状态更新请求（订单取消）
     *
     * @param refundOrder 退款订单
     * @return 订单状态更新请求
     */
    private OrderRefundNotifyReq createOrderRefundNotifyReqForRefundFail(RefundOrderEntity refundOrder) {
        log.info("开始创建订单取消退款失败时的订单状态更新请求，退款订单：{}", refundOrder);
        OrderRefundNotifyReq orderRefundNotifyReq = new OrderRefundNotifyReq();
        orderRefundNotifyReq.setOrderSn(refundOrder.getMerchantOrderSn());
        orderRefundNotifyReq.setRefundStatus("FAIL");
        orderRefundNotifyReq.setRefundSn(refundOrder.getRefundSn());
        log.info("创建订单取消退款失败时的订单状态更新请求完成，请求参数：{}", orderRefundNotifyReq);
        return orderRefundNotifyReq;
    }
}