package com.slodon.b2b2c.controller.seller.seller;

import com.slodon.b2b2c.core.config.DomainUrlUtil;
import com.slodon.b2b2c.core.constant.PayConst;
import com.slodon.b2b2c.core.controller.BaseController;
import com.slodon.b2b2c.core.response.JsonResult;
import com.slodon.b2b2c.core.response.SldResponse;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.core.util.UserUtil;
import com.slodon.b2b2c.core.util.WebUtil;
import com.slodon.b2b2c.model.seller.StoreApplyModel;
import com.slodon.b2b2c.model.seller.StoreRenewModel;
import com.slodon.b2b2c.seller.example.StoreApplyExample;
import com.slodon.b2b2c.seller.example.StoreRenewExample;
import com.slodon.b2b2c.seller.pojo.StoreApply;
import com.slodon.b2b2c.seller.pojo.StoreRenew;
import com.slodon.b2b2c.seller.pojo.Vendor;
import com.slodon.b2b2c.starter.entity.SlodonPayRequest;
import com.slodon.b2b2c.starter.entity.cpcn.TxPayRequest;
import com.slodon.b2b2c.starter.pay.SlodonPay;
import com.slodon.b2b2c.starter.util.ZjPayUtil;
import com.slodon.b2b2c.util.PayPropertiesUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import payment.api.util.GUIDGenerator;

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

import static com.slodon.b2b2c.core.constant.PayConst.*;

@Api(tags = "seller-付款接口")
@Slf4j
@RestController
@RequestMapping("seller/pay")
public class PayController extends BaseController {

    private final static String PAY_SUCCESS_URL = "/apply/open_up";
    private final static String PAY_SUCCESS_URL_RENEW = "/store/info";

    @Resource
    private StoreRenewModel storeRenewModel;
    @Resource
    private StoreApplyModel storeApplyModel;
    @Resource
    private SlodonPay slodonPay;
    @Resource
    private PayPropertiesUtil payPropertiesUtil;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @ApiOperation("商户续签支付")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "payMethod", value = "支付方式,三方支付时必传  wx-微信支付，alipay-支付宝支付", required = true),
            @ApiImplicitParam(name = "paySn", value = "支付单号", required = true),
            @ApiImplicitParam(name = "bankCode", value = "银行编码，中金网银支付，编码账号二选一", paramType = "query"),
            @ApiImplicitParam(name = "bankAccount", value = "银行账号，中金网银支付，编码账号二选一", paramType = "query")
    })
    @PostMapping("renewPay")
    public JsonResult<Object> renewPay(HttpServletRequest request, String payMethod, String paySn) throws Exception {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);
        //获取付款金额
        StoreRenewExample storeRenewExample = new StoreRenewExample();
        storeRenewExample.setPaySn(paySn);
        StoreRenew storeRenew = storeRenewModel.getStoreRenewList(storeRenewExample, null).get(0);
        BigDecimal payAmount = storeRenew.getPayAmount();

        //构造三方支付请求参数
        SlodonPayRequest payRequest = this.getPayRequest(payMethod, paySn, payAmount, WebUtil.getRealIp(request), "renew", vendor.getVendorId());
        if (payRequest.getPayMethod().toLowerCase().contains(METHOD_ZJ.toLowerCase())) {
            if (!StringUtils.isEmpty(storeRenew.getTradeSn())) {
                //之前的支付流水号，关闭支付单
                ZjPayUtil.closeOrder(storeRenew.getTradeSn(), stringRedisTemplate.opsForValue().get("zj_pay_institution_id"));
            }
            //中金支付，将支付流水号写入续签表
            StoreRenew update = new StoreRenew();
            update.setRenewId(storeRenew.getRenewId());
            update.setTradeSn(payRequest.getTxPayRequest().getTxSn());
            storeRenewModel.updateStoreRenew(update);
        }

        return SldResponse.success(slodonPay.unitePay(payRequest));
    }

    @ApiOperation("商户入驻支付")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "payMethod", value = "支付方式,三方支付时必传  wx-微信支付，alipay-支付宝支付", required = true),
            @ApiImplicitParam(name = "paySn", value = "支付单号", required = true)
    })
    @PostMapping("registerPay")
    public JsonResult<Object> registerPay(HttpServletRequest request, String payMethod, String paySn) throws Exception {
        Vendor vendor = UserUtil.getUser(request, Vendor.class);
        //获取付款金额
        StoreApplyExample storeApplyExample = new StoreApplyExample();
        storeApplyExample.setPaySn(paySn);
        StoreApply storeApply = storeApplyModel.getStoreApplyList(storeApplyExample, null).get(0);
        BigDecimal payAmount = storeApply.getPayAmount();

        //构造三方支付请求参数
        SlodonPayRequest payRequest = this.getPayRequest(payMethod, paySn, payAmount, WebUtil.getRealIp(request), "register", vendor.getVendorId());
        if (payRequest.getPayMethod().toLowerCase().contains(METHOD_ZJ.toLowerCase())) {
            if (!StringUtils.isEmpty(storeApply.getTradeSn())) {
                //之前的支付流水号，关闭支付单
                ZjPayUtil.closeOrder(storeApply.getTradeSn(), stringRedisTemplate.opsForValue().get("zj_pay_institution_id"));
            }
            //中金支付，将支付流水号写入申请表
            StoreApply update = new StoreApply();
            update.setApplyId(storeApply.getApplyId());
            update.setTradeSn(payRequest.getTxPayRequest().getTxSn());
            storeApplyModel.updateStoreApply(update);
        }

        return SldResponse.success(slodonPay.unitePay(payRequest));
    }

    /**
     * 构造支付请求对象
     *
     * @param payMethod 支付方式
     * @param paySn     支付单号
     * @param payAmount 支付金额
     * @param ip        ip
     * @return 支付请求对象
     */
    private SlodonPayRequest getPayRequest(String payMethod, String paySn, BigDecimal payAmount, String ip, String type, Long vendorId) throws Exception {
        SlodonPayRequest request = new SlodonPayRequest();
        AssertUtil.isTrue(!payMethod.equals(METHOD_WX) && !payMethod.equals(METHOD_ALIPAY) && !payMethod.equals(METHOD_PAYPAL), "支付方式有误");
        if ("1".equals(stringRedisTemplate.opsForValue().get("zjpay_is_enable"))) {
            //中金支付开启
            if (payMethod.equals(METHOD_WX)) {
                payMethod = METHOD_ZJ_WX;
            } else if (payMethod.equals(METHOD_ALIPAY)) {
                payMethod = METHOD_ZJ_ALI;
            }
        }
        request.setPayMethod(payMethod);
        //商品描述
        String body = stringRedisTemplate.opsForValue().get("basic_site_name") + "-商户入驻";
        request.setSubject(body);
        request.setBody(body);
        switch (payMethod) {
            case METHOD_WX:
                //微信支付
                request.setWxPayProperties(payPropertiesUtil.getWxPayProperties());
                if ("renew".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/renewPayCallback/wx");
                } else if ("register".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/registerPayCallback/wx");
                }
                request.setPayType(WX_TYPE_NATIVE);
                break;
            case METHOD_PAYPAL:
                //paypal支付
                request.setPayPalProperties(payPropertiesUtil.getPayPalProperties());
                if ("renew".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/renewPayCallback/payPal");
                } else if ("register".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/registerPayCallback/payPal");
                }
                request.setPayType(PAYPAL_TYPE_NATIVE);
                break;
            case METHOD_ALIPAY:
                //支付宝
                request.setAlipayProperties(payPropertiesUtil.getAliPayProperties());
                if ("renew".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/renewPayCallback/ali");
                    request.setReturnUrl(DomainUrlUtil.SLD_SELLER_URL + PAY_SUCCESS_URL_RENEW);
                } else if ("register".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/registerPayCallback/ali");
                    request.setReturnUrl(DomainUrlUtil.SLD_SELLER_URL + PAY_SUCCESS_URL);
                }
                request.setPayType(ALI_TYPE_NATIVE);
                break;
            default:
                //中金
                request.setPayType(ZJ_TYPE_NATIVE);
                if ("renew".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/renewPayCallback/zj");
                } else if ("register".equals(type)) {
                    request.setNotifyUrl(DomainUrlUtil.SLD_API_URL + "/v3/seller/seller/registerPayCallback/zj");
                }
                request.setTxPayRequest(this.getTxPayRequest(vendorId, payMethod));
                break;
        }
        request.setPaySn(paySn);
        if ("1".equals(stringRedisTemplate.opsForValue().get("pay_test_enable"))) {
            request.setPayAmount(new BigDecimal("0.01"));
        } else {
            request.setPayAmount(payAmount);
        }
        request.setIp(ip);

        return request;
    }

    /**
     * 构造中金支付请求参数
     *
     * @param vendorId  管理员id
     * @param payMethod 支付方式{@link PayConst#METHOD_ZJ_WX}
     * @return 中金支付请求参数
     */
    public TxPayRequest getTxPayRequest(Long vendorId, String payMethod) throws Exception {
        //构造中金支付请求参数
        String institutionId = stringRedisTemplate.opsForValue().get("zj_pay_institution_id");
        AssertUtil.notEmpty(institutionId, "支付方式暂未开通");
        TxPayRequest txPayRequest = new TxPayRequest();
        txPayRequest.setInstitutionId(institutionId);
        txPayRequest.setTxSn(GUIDGenerator.genGUID());
        txPayRequest.setPayerUserId("v" + vendorId);
        txPayRequest.setPayeeUserId(institutionId);
        txPayRequest.setPayeeAccountNumber("0001");
        txPayRequest.setHasSubsequentSplit("1");//无后续分账

        txPayRequest.setGoodsName(stringRedisTemplate.opsForValue().get("basic_site_name"));
        txPayRequest.setPaymentWay("42");
        switch (payMethod) {
            case METHOD_ZJ_WX:
                //微信
                txPayRequest.setScanPaymentType(PayConst.ZJ_QR_TYPE_WX);
                break;
            case METHOD_ZJ_ALI:
                //支付宝
                txPayRequest.setScanPaymentType(ZJ_QR_TYPE_ALI);
                break;
        }

        return txPayRequest;
    }
}
