package com.jeequan.jeepay.thirdparty.channel.sandpay.payway;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.exception.ChannelException;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.sandpay.SandpayNormalMchParams;
import com.jeequan.jeepay.core.model.rqrs.AbstractRS;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.model.rqrs.payorder.UnifiedOrderRQ;
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.SandH5OrderRQ;
import com.jeequan.jeepay.core.model.rqrs.payorder.payway.SandH5OrderRS;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.thirdparty.channel.sandpay.SandpayPaymentService;
import com.jeequan.jeepay.thirdparty.util.ApiResBuilder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.Date;

/**
 * 杉德H5收银台
 *
 * @author jmdhappy
 *
 * @date 2021/12/31 12:11
 */
@Service("sandpayPaymentBySandpH5Service") //Service Name需保持全局唯一性
public class SandH5 extends SandpayPaymentService {

    @Override
    public String preCheck(UnifiedOrderRQ rq, PayOrder payOrder) {

        SandH5OrderRQ bizRQ = (SandH5OrderRQ) rq;
        if(StringUtils.isEmpty(bizRQ.getProductCode())){
            throw new BizException("产品编码[productCode]不可为空");
        }

        return null;
    }

    @Override
    public AbstractRS pay(UnifiedOrderRQ rq, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
        SandH5OrderRS res = ApiResBuilder.buildSuccess(SandH5OrderRS.class);

        SandH5OrderRQ req = (SandH5OrderRQ) rq;
        // 支付类型
        String productCode = req.getProductCode();
        String payType = "";
        switch (productCode) {
            case "02000001":    // 聚合码
                payType = "pczm";
                break;
            case "02010002":    // 微信公众号(微信公众号H5)
                payType = "public";
                break;
            case "02010005":    // APP包装微信小程序(微信sdk)
                payType = "sdk";
                break;
            case "02010006":    // 微信小程序(云函数h5)
                payType = "applet";
                break;
            case "02010007":    // 微信小程序(云函数sdk)
                payType = "sdk";
                break;
            case "02020002":    // 支付宝生活号(支付宝H5)
                payType = "alipayh5";
                break;
            case "02020004":    // APP包装支付宝(支付宝sdk)
                payType = "sdk";
        }

        ChannelRetMsg channelRetMsg = new ChannelRetMsg();
        res.setChannelRetMsg(channelRetMsg);
        try {

            SandpayNormalMchParams mchParams = (SandpayNormalMchParams)configContextQueryService.queryNormalMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), CS.IF_CODE.SANDPAY);

            // 拼接服务端参数
            JSONObject paramsJson = new JSONObject();
            // 当前接口版本号
            paramsJson.put("version", "10");
            // 商户编号
            paramsJson.put("mer_no", mchParams.getMid());
            // 商户密钥, 手机APK工具 生成的key1
            paramsJson.put("mer_key", mchParams.getKey1());
            // 商户订单号（最小长度12位）
            paramsJson.put("mer_order_no", payOrder.getPayOrderId());
            // 订单创建时间 yyyyMMddHHmmss
            paramsJson.put("create_time", DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN));
            // 订单金额（单位:元，1分=0.01元
            paramsJson.put("order_amt", AmountUtil.convertCent2Dollar(payOrder.getFindAmt().toString()));
            // 回调地址
            paramsJson.put("notify_url", getNotifyUrl());
            // 支付后返回的商户显示页面,没有就填""
            paramsJson.put("return_url", getReturnUrl());
            // 用户所在客户端的真实ip其中的“.”替换为“_” 。如 192_168_0_1
            paramsJson.put("create_ip", payOrder.getClientIp().replace(".", "_"));
            // 门店号 没有就填默认值 000000
            paramsJson.put("store_id", "000000");
            // 清算模式（不参加签名）0-T1(默认);1-T0;2-D0;3-D1
            paramsJson.put("clear_cycle", "");
            // 支付扩展域
            paramsJson.put("pay_extra", req.getPayExtra());
            // 分账标识 NO无分账，YES有分账
            paramsJson.put("accsplit_flag", "NO");
            // 签名类型，默认MD5
            paramsJson.put("sign_type", "MD5");

            String sign = JeepayKit.getSign(paramsJson, mchParams.getMd5Key());
            // MD5签名结果
            paramsJson.put("sign", sign);
            // 订单失效时间 yyyyMMddHHmmss（不参加签名）
            paramsJson.put("expire_time", DateUtil.format(payOrder.getExpiredTime(), DatePattern.PURE_DATETIME_PATTERN));
            // 商品名称（不参加签名）
            paramsJson.put("goods_name", payOrder.getSubject());
            // 支付产品,多个以英文逗号分隔，具体产品见产品编码文档（不参加签名）
            paramsJson.put("product_code", productCode);
            // 跳转scheme（不参与签名）没有就填默认值 sandcash://scpay
            paramsJson.put("jump_scheme", "sandcash://scpay");
            // 终端/网站参数
            paramsJson.put("meta_option", req.getMetaOption());

            // 对参数做URL编码处理
            URLEncoder(paramsJson, "mer_key", "goods_name", "notify_url", "return_url", "pay_extra", "meta_option");

            if("sdk".equals(payType)) {
                String urlParams = JeepayKit.genUrlParams(paramsJson);
                res.setFormContent(urlParams);
            }else {
                String urlParams = JeepayKit.genUrlParams(paramsJson);
                res.setPayUrl("https://sandcash.mixienet.com.cn/h5/?" + urlParams + "#/" + payType);
            }

            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);

        }catch (Exception e) {
            throw ChannelException.sysError(e.getMessage());
        }
        return res;
    }

    /**
     *
     * @param obj 需要处理的JSON对象
     * @param keys 需要编码的key集合
     */
    void URLEncoder(JSONObject obj, String... keys) {
        for(String key : keys) {
            if(StringUtils.isNotBlank(obj.getString(key))) {
                obj.put(key, URLEncoder.encode(obj.getString(key)));
            }
        }
    }

}
