package com.slodon.b2b2c.starter.client;

import com.paypal.api.payments.*;
import com.paypal.base.rest.APIContext;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.starter.entity.*;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * PayPal支付客户端
 */
@Slf4j
public class SlodonPayPalClient extends SlodonPayClient {

    /**
     * PayPal client
     */
    private APIContext apiContext;

    /**
     * 支付构造函数
     *
     * @param request
     */
    public SlodonPayPalClient(SlodonPayRequest request) {
        super(request);
        PayPalProperties payPalProperties = request.getPayPalProperties();
        AssertUtil.notNull(payPalProperties, "PayPal支付参数配置无效");

        this.apiContext = new APIContext(payPalProperties.getClientId(), payPalProperties.getSecret(), payPalProperties.getMode());
    }

    /**
     * 退款构造函数
     *
     * @param refundRequest
     */
    @SneakyThrows
    public SlodonPayPalClient(SlodonRefundRequest refundRequest) {
        super(refundRequest);
        PayPalProperties payPalProperties = refundRequest.getPayPalProperties();
        AssertUtil.notNull(payPalProperties, "PayPal支付参数配置无效");

        this.apiContext = new APIContext(payPalProperties.getClientId(), payPalProperties.getSecret(), payPalProperties.getMode());
    }

    /**
     * 执行payPal支付
     *
     * @return
     * @throws Exception
     */
    @Override
    public SlodonPayResponse doPay() throws Exception {
        Amount amount = new Amount();
        amount.setCurrency("USD");
        amount.setTotal(payRequest.getPayAmount().toString());

        Transaction transaction = new Transaction();
        transaction.setAmount(amount);
        transaction.setDescription(payRequest.getBody());
        transaction.setCustom(payRequest.getPaySn());
        transaction.setNotifyUrl(payRequest.getNotifyUrl());

        List<Transaction> transactions = new ArrayList<>();
        transactions.add(transaction);

        Payer payer = new Payer();
        payer.setPaymentMethod("paypal");

        Payment payment = new Payment();
        payment.setIntent("sale");
        payment.setPayer(payer);
        payment.setTransactions(transactions);
        RedirectUrls redirectUrls = new RedirectUrls();
        redirectUrls.setCancelUrl(payRequest.getReturnUrl());
        redirectUrls.setReturnUrl(payRequest.getReturnUrl());
        payment.setRedirectUrls(redirectUrls);

        Payment paymentResponse = payment.create(apiContext);
        SlodonPayResponse response = new SlodonPayResponse();
        response.setActionType("redirect");
        for (Links links : paymentResponse.getLinks()) {
            if ("approval_url".equals(links.getRel())) {
                response.setPayData(links.getHref());
                break;
            }
        }
        response.setOrderId(paymentResponse.getId());
        return response;
    }

    /**
     * 执行退款
     */
    @Override
    public SlodonRefundResponse doRefund() throws Exception {
        //构造业务参数
        RefundRequest refund = new RefundRequest();
        Amount amount = new Amount();
        amount.setCurrency("USD");
        amount.setTotal(this.refundRequest.getRefundAmount().toString());
        refund.setAmount(amount);
        refund.setReason("payPal退款");

        Sale sale = new Sale();
        sale.setId(this.refundRequest.getTradeSn());
        //执行退款
        DetailedRefund detailedRefund = sale.refund(apiContext, refund);
        log.info("退款状态===================================================：" + detailedRefund.getState());
        //构造返回数据
        SlodonRefundResponse refundResponse = new SlodonRefundResponse();
        refundResponse.setSuccess("completed".equals(detailedRefund.getState()));
        refundResponse.setMsg(detailedRefund.getDescription());
        return refundResponse;
    }

    @Override
    public SlodonTransfersResponse doTransfers() throws Exception {
        return null;
    }

    @Override
    public void checkPayState(String tradeNo, String outTradeNo, String payType) throws Exception {

    }
}
