package com.wzj.soopin.transaction.kit.plugin.wallet;


import com.wzj.soopin.member.enums.AccountBillChangeTypeEnum;
import com.wzj.soopin.member.enums.AccountBillSourceEnum;
import com.wzj.soopin.member.enums.AccountTypeEnum;
import com.wzj.soopin.member.service.IMemberAccountService;
import com.wzj.soopin.transaction.domain.po.RefundLog;
import com.wzj.soopin.transaction.enums.CashierEnum;
import com.wzj.soopin.transaction.enums.PaymentMethodEnum;
import com.wzj.soopin.transaction.kit.CashierSupport;
import com.wzj.soopin.transaction.kit.Payment;
import com.wzj.soopin.transaction.kit.dto.PayParam;
import com.wzj.soopin.transaction.kit.dto.PaymentSuccessParams;
import com.wzj.soopin.transaction.kit.params.dto.CashierParam;
import com.wzj.soopin.transaction.service.IAccountBillService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.ResultCode;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.event.Constants;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.satoken.utils.LoginHelper;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;


/**
 * WalletPlugin
 *
 * @author Chopper
 * @version v1.0
 * 2021-02-20 10:14
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class WalletPlugin implements Payment {

    /**
     * 支付日志
     */
//    private final paymentService;
    /**
     * 退款日志
     */
//    private final RefundLogService refundLogService;
    /**
     * 会员余额
     */
    private final IAccountBillService accountBillService;
    /**
     * 收银台
     */
    private final CashierSupport cashierSupport;

    private final RedissonClient redisson;

    @Override
    public R<Object> h5pay(HttpServletRequest request, HttpServletResponse response, PayParam payParam) {
        savePaymentLog(payParam);
        return R.ok(ResultCode.PAY_SUCCESS);
    }

    @Override
    public R<Object> jsApiPay(HttpServletRequest request, PayParam payParam) {
        savePaymentLog(payParam);
        return R.ok(ResultCode.PAY_SUCCESS);
    }

    @Override
    public R<Object> appPay(HttpServletRequest request, PayParam payParam) {
        savePaymentLog(payParam);
        return R.ok(ResultCode.PAY_SUCCESS);
    }

    @Override
    public R<Object> nativePay(HttpServletRequest request, PayParam payParam) {
        if (payParam.getOrderType().equals(CashierEnum.RECHARGE.name())) {
            throw new ServiceException(ResultCode.CAN_NOT_RECHARGE_WALLET);
        }
        savePaymentLog(payParam);
        return R.ok(ResultCode.PAY_SUCCESS);
    }

    @Override
    public R<Object> mpPay(HttpServletRequest request, PayParam payParam) {

        savePaymentLog(payParam);
        return R.ok(ResultCode.PAY_SUCCESS);
    }

    @Override
    public void cancel(RefundLog refundLog) {

        try {
//            memberWalletService.increase(new MemberWalletUpdateDTO(refundLog.getTotalAmount(),
//                    refundLog.getMemberId(),
//                    "取消[" + refundLog.getOrderSn() + "]订单，退还金额[" + refundLog.getTotalAmount() + "]",
//                    DepositServiceTypeEnum.WALLET_REFUND.name()));
//            refundLog.setIsRefund(true);
//            refundLogService.save(refundLog);
        } catch (Exception e) {
            log.error("订单取消错误", e);
        }
    }

    /**
     * 保存支付日志
     *
     * @param payParam 支付参数
     */
    private void savePaymentLog(PayParam payParam) {
        //同一个会员如果在不同的客户端使用预存款支付，会存在同时支付，无法保证预存款的正确性，所以对会员加锁

        LoginUser loginUser = LoginHelper.getLoginUser();
        if (loginUser == null) {
            throw new ServiceException("用户未登录");
        }
        RLock lock = redisson.getLock(loginUser + "");
        lock.lock();
        try {
            //获取支付收银参数
            CashierParam cashierParam = cashierSupport.cashierParam(payParam);
            this.callBack(payParam, cashierParam);
        } catch (Exception e) {
            throw e;
        } finally {
            lock.unlock();
        }
    }

    @Override
    public void refund(RefundLog refundLog) {
        try {
//            memberWalletService.increase(new MemberWalletUpdateDTO(refundLog.getTotalAmount(),
//                    refundLog.getMemberId(),
//                    "售后[" + refundLog.getAfterSaleNo() + "]审批，退还金额[" + refundLog.getTotalAmount() + "]",
//                    DepositServiceTypeEnum.WALLET_REFUND.name()));
//            refundLog.setIsRefund(true);
//            refundLogService.save(refundLog);
        } catch (Exception e) {
            log.error("退款失败", e);
        }
    }

    /**
     * 支付订单
     *
     * @param payParam     支付参数
     * @param cashierParam 收银台参数
     */
    public void callBack(PayParam payParam, CashierParam cashierParam) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        //支付信息
        try {
            if (loginUser.getUserId() == null) {
                throw new ServiceException(ResultCode.USER_NOT_LOGIN);
            }
            //个人账户扣减
            boolean result = accountBillService.reduceMoney(
                            BigDecimal.valueOf(cashierParam.getPrice() ),
                            loginUser.getUserId(),

                AccountBillSourceEnum.PAYMENT,
                            "订单[" + cashierParam.getOrderSns() + "]支付金额[" + cashierParam.getPrice() + "]"
            );
            //更新支付日志
            if (result) {
                try {
//                    PaymentSuccessParams paymentSuccessParams = new PaymentSuccessParams(
//                            PaymentMethodEnum.WALLET.name(),
//                            "",
//                            cashierParam.getPrice(),
//                            payParam
//                    );
//
//                    paymentService.success(paymentSuccessParams);
                    log.info("支付回调通知：余额支付：{}", payParam);
                } catch (ServiceException e) {
                    //业务异常，则支付手动回滚
//                    memberWalletService.increase(new MemberWalletUpdateDTO(
//                            cashierParam.getPrice(),
//                            UserContext.getCurrentUser().getId(),
//                            "订单[" + cashierParam.getOrderSns() + "]支付异常，余额返还[" + cashierParam.getPrice() + "]",
//                            DepositServiceTypeEnum.WALLET_REFUND.name())
//                    );
                    throw e;
                }
            } else {
                throw new ServiceException(ResultCode.WALLET_INSUFFICIENT);
            }
        } catch (ServiceException e) {
            throw e;
        } catch (Exception e) {
            log.info("余额支付异常", e);
            throw new ServiceException(ResultCode.WALLET_INSUFFICIENT);
        }

    }

}
