package com.hzs.third.pay.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hzs.common.core.constant.MagicNumberConstants;
import com.hzs.common.core.constant.RabbitMqConstants;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.domain.third.pay.TOnlinePayment;
import com.hzs.member.account.IMemberTradeServiceApi;
import com.hzs.retail.sale.IRetailOrderServiceApi;
import com.hzs.sale.ticket.ITicketServiceApi;
import com.hzs.third.mq.dto.RefundOrderDTO;
import com.hzs.third.pay.service.*;
import com.hzs.third.pay.util.PayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 基础支付服务
 */
@Slf4j
@Service
public class PayServiceImpl implements IPayService {

    @Autowired
    private ITOnlinePaymentService itOnlinePaymentService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @DubboReference
    IRetailOrderServiceApi iRetailOrderServiceApi;
    @DubboReference
    IMemberTradeServiceApi iMemberTradeServiceApi;
    @DubboReference
    ITicketServiceApi iTicketServiceApi;

    /**
     * 支付回调处理
     *
     * @param businessType  支付业务类型（与支付扩展类保持一致）
     * @param businessCode  支付业务单号
     * @param originalOrder 三方订单号
     * @param payNumber     支付流水号（支付回调流水号）
     * @param payTime       支付时间（支付回调成功时间）
     * @param payMoney      支付金额（支付回调金额）
     * @param ePayChannel   支付渠道
     * @param channelNumber 支付渠道流水号（微信、支付宝等流水号）
     * @return
     */
    @Override
    public boolean notifyHandle(String businessType, String businessCode, String originalOrder,
                                String payNumber, Date payTime, BigDecimal payMoney,
                                EPayChannel ePayChannel, String channelNumber) {
        // 校验支付信息状态、业务与支付金额是否一致等
        TOnlinePayment onlinePayment = itOnlinePaymentService.queryByBusiness(
                ObjectUtil.isNotEmpty(businessType) ? Integer.valueOf(businessType) : null
                , businessCode, null);
        if (null == onlinePayment || EPayStatus.PAID.getValue() == onlinePayment.getPayStatus()) {
            log.error("支付信息不存在或已支付");
            return false;
        }

        try {
            if (!PayUtil.checkAmount(onlinePayment.getBusinessMoney(), payMoney)) {
                // 业务金额 大于 实际支付金额
                log.error("业务金额大于实际支付金额，支付编号：{}, 支付金额：{}", onlinePayment.getPaymentCode(), payMoney);
            }

            onlinePayment.setPayStatus(EPayStatus.PAID.getValue());
            onlinePayment.setPayNumber(payNumber);
            onlinePayment.setPayTime(payTime);
            onlinePayment.setPayMoney(payMoney);
            onlinePayment.setOriginalOrder(originalOrder);
            onlinePayment.setChannelNumber(channelNumber);
            onlinePayment.setPkModified(MagicNumberConstants.PK_ADMIN);
            onlinePayment.setModifiedTime(new Date());
            if (null != ePayChannel) {
                onlinePayment.setPayChannel(ePayChannel.getValue());
            }
            // 更新支付相关信息
            if (itOnlinePaymentService.updateById(onlinePayment)) {
                // 进行支付业务处理
                this.handleBusiness(onlinePayment, true);
                // 更新业务处理信息
                itOnlinePaymentService.updateById(onlinePayment);

                return true;
            }
        } catch (Exception e) {
            log.error("在线支付信息回调处理异常", e);

            // 更新业务处理信息
            itOnlinePaymentService.update(Wrappers.<TOnlinePayment>lambdaUpdate()
                    .eq(TOnlinePayment::getPkId, onlinePayment.getPkId())
                    .set(TOnlinePayment::getCallbackStatus, ECallbackStatus.FAIL.getValue())
                    .set(TOnlinePayment::getCallbackInfo, e.getMessage())
            );
        }
        return false;
    }

    @Override
    public boolean notifyHandle(String businessType, String businessCode, String originalOrder, String payNumber,
                                Date payTime, BigDecimal payMoney, EPayChannel ePayChannel, String channelNumber,
                                Integer payType, String acqOrderId) {
        // 校验支付信息状态、业务与支付金额是否一致等
        TOnlinePayment onlinePayment = itOnlinePaymentService.queryByBusiness(
                ObjectUtil.isNotEmpty(businessType) ? Integer.valueOf(businessType) : null
                , businessCode, null);
        if (null == onlinePayment || EPayStatus.PAID.getValue() == onlinePayment.getPayStatus()) {
            log.error("支付信息不存在或已支付");
            return false;
        }

        try {
            if (!PayUtil.checkAmount(onlinePayment.getBusinessMoney(), payMoney)) {
                // 业务金额 大于 实际支付金额
                log.error("业务金额大于实际支付金额，支付编号：{}, 支付金额：{}", onlinePayment.getPaymentCode(), payMoney);
            }

            onlinePayment.setPayStatus(EPayStatus.PAID.getValue());
            onlinePayment.setPayNumber(payNumber);
            onlinePayment.setPayTime(payTime);
            onlinePayment.setPayMoney(payMoney);
            onlinePayment.setOriginalOrder(originalOrder);
            onlinePayment.setChannelNumber(channelNumber);
            onlinePayment.setPkModified(MagicNumberConstants.PK_ADMIN);
            onlinePayment.setModifiedTime(new Date());
            onlinePayment.setPayType(payType);
            onlinePayment.setChannelNumber(acqOrderId);
            if (null != ePayChannel) {
                onlinePayment.setPayChannel(ePayChannel.getValue());
            }
            // 更新支付相关信息
            if (itOnlinePaymentService.updateById(onlinePayment)) {
                // 进行支付业务处理
                this.handleBusiness(onlinePayment, true);
                // 更新业务处理信息
                itOnlinePaymentService.updateById(onlinePayment);

                return true;
            }
        } catch (Exception e) {
            log.error("在线支付信息回调处理异常", e);

            // 更新业务处理信息
            itOnlinePaymentService.update(Wrappers.<TOnlinePayment>lambdaUpdate()
                    .eq(TOnlinePayment::getPkId, onlinePayment.getPkId())
                    .set(TOnlinePayment::getCallbackStatus, ECallbackStatus.FAIL.getValue())
                    .set(TOnlinePayment::getCallbackInfo, e.getMessage())
            );
        }
        return false;
    }

    @Override
    public boolean retryHandle(TOnlinePayment tOnlinePayment, boolean mqPush) {
        // 支付业务处理
        boolean handBool = this.handleBusiness(tOnlinePayment, mqPush);
        if (handBool) {
            // 更新支付信息
            itOnlinePaymentService.updateById(tOnlinePayment);
        }

        return handBool;
    }

    /**
     * 支付业务处理
     *
     * @param onlinePayment 在线支付明细
     * @param mqPush        是否推送MQ
     * @return
     */
    private boolean handleBusiness(TOnlinePayment onlinePayment, boolean mqPush) {
        // 业务类型
        EPayBusinessType payBusinessType = EPayBusinessType.getEnumByValue(onlinePayment.getBusinessType());
        if (null != payBusinessType) {
            // 服务调用结果（0=没有业务处理，1=成功，2=失败）
            int resultInt = 0;
            // 服务调用返回信息
            String resultMsg = "";
            // 根据业务类型调用具体业务处理 dubbo 服务
            switch (payBusinessType) {
                case MEMBER_ORDER:
                    // 会员订单
                    R<?> orderResult = iRetailOrderServiceApi.onlinePaymentCallBack(onlinePayment.getPkCreator(), onlinePayment.getBusinessCode());
                    log.info("会员订单在线支付业务回调处理： success: {}, data: {}", orderResult.isSuccess(), orderResult.getData());
                    if (orderResult.isSuccess()) {
                        resultInt = 1;
                    } else {
                        resultInt = 2;
                        resultMsg = orderResult.getMsg();

                        if (mqPush) {
                            log.error("会员订单支付回调失败，推送MQ处理");
                            // 直销订单处理失败，发送MQ，进行原路退款
                            rabbitTemplate.convertAndSend(RabbitMqConstants.REFUND_ORDER_EXCHANGE, RabbitMqConstants.REFUND_ORDER_KEY,
                                    RefundOrderDTO.builder()
                                            .pkMember(onlinePayment.getPkCreator())
                                            .orderCode(onlinePayment.getBusinessCode())
                                            .payBusinessType(EPayBusinessType.MEMBER_ORDER.getValue())
                                            .build());
                        }
                    }
                    break;
                case RECHARGE:
                    // 充值
                    R<?> rechargeResult = iMemberTradeServiceApi.updateOnlineRechargeByRechargeCode(onlinePayment.getBusinessCode(), EApproveOperation.AGREE, onlinePayment.getPkCreator());
                    if (rechargeResult.isSuccess()) {
                        resultInt = 1;
                    } else {
                        resultInt = 2;
                        resultMsg = rechargeResult.getMsg();
                    }
                    break;
                case TICKET:
                    // 购票
                    R<?> ticketResult = iTicketServiceApi.paySaTicketOnlineOrderCode(onlinePayment.getPkCreator(), onlinePayment.getBusinessCode());
                    if (ticketResult.isSuccess()) {
                        resultInt = 1;
                    } else {
                        resultInt = 2;
                        resultMsg = ticketResult.getMsg();
                    }
                    break;
                default:
            }

            if (0 != resultInt) {
                if (1 == resultInt) {
                    // 调用业务处理成功、失败，如果失败记录原因
                    onlinePayment.setCallbackStatus(ECallbackStatus.SUCCESS.getValue());
                    onlinePayment.setCallbackInfo("");
                    return true;
                } else {
                    onlinePayment.setCallbackStatus(ECallbackStatus.FAIL.getValue());
                    onlinePayment.setCallbackInfo(resultMsg);
                    return false;
                }
            } else {
                log.error("支付回调没有后续业务处理");
                onlinePayment.setCallbackInfo("支付回调没有后续业务处理");
                return false;
            }
        }
        log.error("支付业务处理失败，不存在的业务类型");
        return false;
    }


}
