package beilv.pay.service.impl;

import beilv.pay.config.WxPayConfig;
import beilv.pay.service.WxUserPayService;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import com.wechat.pay.java.service.refund.model.RefundNotification;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.math.BigDecimal;

@Service
@Slf4j
public class WxUserPayServiceImpl implements WxUserPayService {

    @Resource
    private WxPayConfig wxPayConfig;
//    @Resource
//    private UserOrderMapper userOrderMapper;
    /**
     * 请求参数
     */
    public static RequestParam requestParam = null;

    @Override
    public PrepayWithRequestPaymentResponse creationIndentPayment(String orderId, String myOpenId, Double amount) {
        PrepayRequest request = new PrepayRequest();
        // 金额
        Amount WxAmount = new Amount();
        WxAmount.setTotal(new BigDecimal(String.valueOf(amount)).movePointRight(2).intValue());
        WxAmount.setCurrency("CNY");
        request.setAmount(WxAmount);
        // 公众号appId
        request.setAppid(wxPayConfig.getAppId());
        // 商户号
        request.setMchid(wxPayConfig.getMerchantId());
        // 支付者信息
        Payer payer = new Payer();
        payer.setOpenid(myOpenId);
        request.setPayer(payer);
        // 描述
        request.setDescription("代办服务");
        // 微信回调地址
        request.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/end/IndentPayment");
        //系统内部订单号
        request.setOutTradeNo(orderId);
        //返回数据，前端调起支付
        return wxPayConfig.getJsapiServiceExtension().prepayWithRequestPayment(request);
    }

    // 获取支付回调信息
    @Override
    public Transaction getTransaction(HttpServletRequest request) {
        NotificationParser notificationParser = getNotificationParser(request);
        return notificationParser.parse(requestParam, Transaction.class);
    }

    // 支付回调
    @Override
    public boolean indentPaymentBlack(Transaction transaction) {
        System.out.println("---------------------------修改订单状态信息(下单)-------------------------------");
        // 获取订单号
        String orderId = transaction.getOutTradeNo();
//        UserOrder userOrder = userOrderMapper.selectById(orderId);
//        if (userOrder == null) {
//            log.error("订单不存在");
//            throw new BusinessException(40004,"订单不存在：" + transaction.getOutTradeNo());
//        }
//        log.info("下单成功");
//        LambdaUpdateWrapper<UserOrder> updateWrapper = new LambdaUpdateWrapper<>();
//        updateWrapper.set(UserOrder::getIsTrue,"已支付").eq(UserOrder::getOrderId,orderId);
//        userOrderMapper.update(null,updateWrapper);
        System.out.println("---------------------------修改订单状态信息完毕-------------------------------");
        System.out.println("---------------------------添加微信支付记录完毕-------------------------------");
        return true;
    }

    @Override
    public Refund refundIndentPayment(String refundId, Double amount) {
        // 退款请求
        CreateRequest createRequest = new CreateRequest();
        // 商户订单号
        createRequest.setOutTradeNo(refundId);
        // 商户退款单号
        createRequest.setOutRefundNo(refundId);
        // 退款结果回调
        createRequest.setNotifyUrl(wxPayConfig.getNotifyUrl() + "/refund/black");
        // 退款金额
        AmountReq amountReq = new AmountReq();
        long refundAmount = new BigDecimal(String.valueOf(amount)).movePointRight(2).intValue();
        amountReq.setRefund(refundAmount);
        amountReq.setTotal(refundAmount);
        amountReq.setCurrency("CNY");
        createRequest.setAmount(amountReq);
        // 申请退款
        System.out.println("退款请求：" + createRequest);
        Refund refund = wxPayConfig.getRefundService().create(createRequest);
        System.out.println("退款申请结果：" + refund);
        return refund;
    }

    // 获取退款回调信息
    @Override
    public RefundNotification getRefundNotification(HttpServletRequest request) {
        NotificationParser notificationParser = getNotificationParser(request);
        return notificationParser.parse(requestParam, RefundNotification.class);
    }

    // 退款回调
    @Override
    public boolean refundIndentBlack(RefundNotification refundNotification) {
        System.out.println("---------------------------修改订单状态信息（退款）-------------------------------");
        // 获取订单号
        String indentIdByString = refundNotification.getOutTradeNo();
        System.out.println("---------------------------修改订单状态信息完毕-------------------------------");
        return true;
    }

    /**
     * 根据微信官方发送的请求获取信息
     */
    @SneakyThrows
    public NotificationParser getNotificationParser(HttpServletRequest request) {
        System.out.println("---------------------------获取信息-------------------------------");
        // 获取RSA配置
        NotificationParser notificationParser = new NotificationParser(wxPayConfig.getRSAConfig());
        // 构建请求
        StringBuilder bodyBuilder = new StringBuilder();
        BufferedReader reader = request.getReader();
        String line;
        while ((line = reader.readLine()) != null) {
            bodyBuilder.append(line);
        }
        String body = bodyBuilder.toString();
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String signature = request.getHeader("Wechatpay-Signature");
        String singType = request.getHeader("Wechatpay-Signature-Type");
        String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");
        requestParam = new RequestParam.Builder()
                .serialNumber(wechatPayCertificateSerialNumber)
                .nonce(nonce)
                .signature(signature)
                .timestamp(timestamp)
                .signType(singType)
                .body(body)
                .build();
        System.out.println(requestParam.toString());
        System.out.println("---------------------------信息获取完毕-------------------------------");
        return notificationParser;
    }
}
