package com.slodon.b2b2c.starter.client;

import com.alibaba.fastjson.JSON;
import com.slodon.b2b2c.core.config.DomainUrlUtil;
import com.slodon.b2b2c.core.exception.MallException;
import com.slodon.b2b2c.core.util.AssertUtil;
import com.slodon.b2b2c.starter.entity.*;
import com.slodon.b2b2c.starter.entity.cpcn.TxPayRequest;
import com.slodon.b2b2c.starter.entity.cpcn.TxRefundRequest;
import com.slodon.b2b2c.starter.util.ZjPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import payment.api.tx.aggregate.*;

import java.math.BigDecimal;

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


/**
 * 中金支付客户端
 */
@Slf4j
public class SlodonZjPayClient extends SlodonPayClient {
    /**
     * 支付构造函数
     *
     * @param payRequest
     */
    public SlodonZjPayClient(SlodonPayRequest payRequest) {
        super(payRequest);
        TxPayRequest txPayRequest = payRequest.getTxPayRequest();
        AssertUtil.notNull(txPayRequest,"中金支付参数无效");
    }

    /**
     * 退款构造函数
     *
     * @param refundRequest
     */
    public SlodonZjPayClient(SlodonRefundRequest refundRequest) {
        super(refundRequest);
        TxRefundRequest txRefundRequest = refundRequest.getTxRefundRequest();
        AssertUtil.notNull(txRefundRequest,"中金退款参数无效");
    }

    /**
     * 执行支付
     *
     * @return
     * @throws Exception
     */
    @Override
    public SlodonPayResponse doPay() throws Exception {
        TxPayRequest txPayRequest = payRequest.getTxPayRequest();
        //拼接请求参数
        Tx5011Request request = new Tx5011Request();
        request.setInstitutionID(txPayRequest.getInstitutionId());
        request.setTxSN(txPayRequest.getTxSn());
        request.setOrderNo(payRequest.getPaySn() + "000000");
        request.setPayerUserID(txPayRequest.getPayerUserId());
        request.setPayeeUserID(txPayRequest.getPayeeUserId());
        request.setPayeeAccountNumber(txPayRequest.getPayeeAccountNumber());
        request.setPaymentWay(txPayRequest.getPaymentWay());
        //将支付金额转为分
        Integer amount = payRequest.getPayAmount().multiply(new BigDecimal(100)).intValue();
        request.setAmount(String.valueOf(amount));
        request.setExpirePeriod(txPayRequest.getExpirePeriod());
        request.setPageURL(txPayRequest.getPageUrl());
        if (DomainUrlUtil.ZJ_PAY_TEST.equals(1)){
            //测试环境
            request.setGoodsName("10");
            if (payRequest.getPayMethod().contains("wx")){
                request.setPlatformName("31");
            }else {
                request.setPlatformName("32");
            }
        }else {
            request.setGoodsName(txPayRequest.getGoodsName());
            request.setPlatformName(txPayRequest.getPlatformName());
        }
        request.setHasSubsequentSplit(txPayRequest.getHasSubsequentSplit());//有后续分账
        request.setNoticeURL(payRequest.getNotifyUrl());
        request.setBankAccountType(txPayRequest.getBankAccountType());
        request.setBankCardType(txPayRequest.getBankCardType());
        request.setBankID(txPayRequest.getBankID());
        request.setRedirectSource(txPayRequest.getRedirectSource());
        request.setPayWay(txPayRequest.getPayWay());
        request.setPayType(txPayRequest.getPayType());
        request.setSubAppID(txPayRequest.getSubAppID());
        request.setSubOpenID(txPayRequest.getSubOpenID());
        request.setScanPaymentType(txPayRequest.getScanPaymentType());
        request.setScanPaymentWay(txPayRequest.getScanPaymentWay());
        request.setCancelPayRedirectPageURL(txPayRequest.getCancelPayRedirectPageURL());
        request.setRedirectPageURL(txPayRequest.getRedirectPageURL());
        request.setDeductionSettlementFlag("0001");

        //获取响应
        String[] respMsg = ZjPayUtil.sendAndGet(request);
        Tx5011Response txResponse = new Tx5011Response(respMsg[0], respMsg[1]);

        if (!"2000".equals(txResponse.getCode())){
            //请求失败
            log.error("中金支付异常：" + txResponse.getMessage());
            throw new MallException("支付功能维护中，请稍后再试");
        }
        log.debug("中金支付响应信息：" + JSON.toJSONString(txResponse));

        /*
         * 支付状态:
           10=未支付
           20=支付处理中
           30=支付成功
           40=支付失败
           50=订单关闭
         */
        String status = txResponse.getStatus();
        AssertUtil.isTrue("50".equals(status),"交易关闭，请重新提交支付请求");
        AssertUtil.isTrue("40".equals(status),"支付失败，请重新提交支付请求");
        if ("30".equals(status)){
            //支付成功，余额支付会出现
            log.debug("=====================================================");
            log.debug("支付成功:" + payRequest.getPayMethod());
            log.debug("=====================================================");
            return new SlodonPayResponse();
        }
        if (!"20".equals(status)){
            throw new MallException("支付功能维护中，请稍后再试");
        }

        //根据支付类型判断返回信息
        if (payRequest.getPayMethod().equals(METHOD_ZJ)){
            //后台余额转账，无需返回数据
            return new SlodonPayResponse();
        }
        if (payRequest.getPayMethod().equals(METHOD_ZJ_BANK)){
            //网银支付，返回网银跳转地址
            return new SlodonPayResponse("eBank",txResponse.getEBankPayURL());
        }
        if (payRequest.getPayMethod().equals(METHOD_ZJ_ALI)){
            //支付宝，自动提交表单
            return new SlodonPayResponse("autopost",txResponse.getQRImageURL());
        }
        switch (payRequest.getPayType()){
            case ZJ_TYPE_NATIVE:
                //扫码支付
                return new SlodonPayResponse("native",txResponse.getQRImageURL());
            case ZJ_TYPE_MWEB:
                return new SlodonPayResponse("redirect",txResponse.getQRAuthCode());
            case ZJ_TYPE_APP:
            case ZJ_TYPE_JSAPI:
            case ZJ_TYPE_MINIAPP:
                //跳转支付
                return new SlodonPayResponse(null,txResponse.getQRAuthCode());
            default:
                log.error("支付方式有误:" + payRequest.getPayType());
                throw new MallException("支付方式有误");
        }
    }

    /**
     * 检测支付状态
     *
     * @param tradeNo    三方支付流水号
     * @param outTradeNo 商城的支付单号
     * @param payType 支付类型
     * @return
     */
    @Override
    public void checkPayState(String tradeNo, String outTradeNo, String payType) throws Exception {
        TxPayRequest txPayRequest = payRequest.getTxPayRequest();
        //拼接请求参数
        Tx5016Request tx5016Request = new Tx5016Request();
        tx5016Request.setInstitutionID(txPayRequest.getInstitutionId());
        tx5016Request.setTxSN(txPayRequest.getTxSn());

        //获取响应
        String[] respMsg = ZjPayUtil.sendAndGet(tx5016Request);
        Tx5016Response txResponse = new Tx5016Response(respMsg[0], respMsg[1]);
        String status = txResponse.getStatus();
        if (StringUtils.isEmpty(status)){
            //查询失败
            log.debug("查询中金支付订单[" + txPayRequest.getTxSn() + "]失败:" + txResponse.getMessage());
        }
        log.debug("查询结果：" + JSON.toJSONString(txResponse));
    }



    /**
     * 执行退款
     */
    @Override
    public SlodonRefundResponse doRefund() throws Exception {
        TxRefundRequest txRefundRequest = refundRequest.getTxRefundRequest();
        //拼接请求参数
        Tx5021Request request = new Tx5021Request();
        request.setInstitutionID(txRefundRequest.getInstitutionId());
        request.setTxSN(txRefundRequest.getTxSn());
        request.setPaymentTxSN(txRefundRequest.getPaymentTxSn());
        request.setRefundWay(txRefundRequest.getRefundWay());
        //将支付金额转为分
        Integer amount = refundRequest.getRefundAmount().multiply(new BigDecimal(100)).intValue();
        request.setAmount(String.valueOf(amount));
        request.setNoticeURL(txRefundRequest.getNoticeUrl());
        request.setRemark(txRefundRequest.getRemark());

        //获取响应
        String[] respMsg = ZjPayUtil.sendAndGet(request);
        Tx5021Response txResponse = new Tx5021Response(respMsg[0], respMsg[1]);

        if (!"2000".equals(txResponse.getCode())){
            //请求失败
            log.error("中金退款异常：" + txResponse.getMessage());
            return new SlodonRefundResponse(false,txResponse.getMessage());
        }
        log.debug("中金退款响应信息：" + JSON.toJSONString(txResponse));
        String status = txResponse.getStatus();
        if ("10".equals(status) || "20".equals(status)){
            return new SlodonRefundResponse(true,"");
        }
        return new SlodonRefundResponse(false,txResponse.getResponseMessage());
    }

    /**
     * 执行转账
     */
    @Override
    public SlodonTransfersResponse doTransfers() throws Exception {
        return null;
    }
}
