package ink.wgink.module.wechat.service.pay.v3.jsapi.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.module.wechat.enums.PayAuthorizationTypeEnum;
import ink.wgink.module.wechat.pojo.pay.v3.PaySign;
import ink.wgink.module.wechat.pojo.pay.v3.jsapi.pojo.PayPlaceOrder;
import ink.wgink.module.wechat.pojo.pay.v3.jsapi.pojo.PayPrepay;
import ink.wgink.module.wechat.remote.pay.v3.IOrderPayRemoteService;
import ink.wgink.module.wechat.service.pay.BasePayService;
import ink.wgink.module.wechat.service.pay.v3.jsapi.IJsapiService;
import ink.wgink.module.wechat.utils.pay.PayPrivateKeyUtil;
import ink.wgink.properties.wechat.miniapp.MiniappProperties;
import ink.wgink.util.BeanPropertyCheckUtil;
import ink.wgink.util.UUIDUtil;
import ink.wgink.util.string.WStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMethod;

import java.util.List;

/**
 * @ClassName: JsapiServiceImpl
 * @Description: Jsapi业务
 * @Author: wanggeng
 * @Date: 2021/8/19 10:42 上午
 * @Version: 1.0
 */
@Service
public class JsapiServiceImpl extends BasePayService implements IJsapiService {


    @Autowired
    private MiniappProperties miniappProperties;
    @Autowired
    private IOrderPayRemoteService orderPayRemoteService;

    @Override
    public PaySign placeOrder(PayPlaceOrder payPlaceOrder) throws Exception {
        payPlaceOrder.setAppid(miniappProperties.getAppKey());
        payPlaceOrder.setMchid(payProperties.getMchid());
        BeanPropertyCheckUtil.checkField(payPlaceOrder);
        String urlSuffix = "/v3/pay/transactions/jsapi";

        LOG.debug("获得证书序列号");
        String serialNumber = getSerialNumber();

        LOG.debug("调用微信支付，发起预支付");
        JSONObject body = getPlaceOrderJsonObject(payPlaceOrder);
        String authorization = getAuthorization(RequestMethod.POST, urlSuffix, serialNumber, payProperties, body.toString(), PayAuthorizationTypeEnum.WECHATPAY2_SHA256_RSA2048);

        LOG.debug("请求获得结果");
        PayPrepay payPrepay = orderPayRemoteService.placeOrderJsapi(getPayBaseUrl(), authorization, serialNumber, body);

        LOG.debug("生成返回结果");
        long timestamp = System.currentTimeMillis() / 1000;
        String nonceStr = WStringUtil.randomSubStr(UUIDUtil.get32UUID(), 10).toUpperCase();

        PaySign paySign = new PaySign();
        paySign.setAppId(miniappProperties.getAppKey());
        paySign.setPrepayId(payPrepay.getPrepayId());
        paySign.setNonceStr(nonceStr);
        paySign.setTimestamp(String.valueOf(timestamp));
        paySign.setPaySign(getPaySign(timestamp, nonceStr, payPrepay.getPrepayId()));
        return paySign;
    }

    /**
     * 没问题会删除`
    public PaySign placeOrder(PayPlaceOrder payPlaceOrder) throws Exception {
        payPlaceOrder.setAppid(miniappProperties.getAppKey());
        payPlaceOrder.setMchid(payProperties.getMchid());
        BeanPropertyCheckUtil.checkField(payPlaceOrder);
        String urlSuffix = "/v3/pay/transactions/jsapi";
        String url = getPayBaseUrl() + urlSuffix;

        LOG.debug("获得证书序列号");
        String serialNumber = getSerialNumber();

        LOG.debug("调用微信支付，发起预支付");
        PlaceOrderPayRequestImpl placeOrderPayRequest = new PlaceOrderPayRequestImpl();
        JSONObject body = getPlaceOrderJsonObject(payPlaceOrder);
        String authorization = getAuthorization(RequestMethod.POST, urlSuffix, serialNumber, payProperties, body.toString(), PayAuthorizationTypeEnum.WECHATPAY2_SHA256_RSA2048);

        LOG.debug("请求获得结果");
        PayPrepay payPrepay = placeOrderPayRequest.post(url, authorization, serialNumber, body);

        LOG.debug("生成返回结果");
        long timestamp = System.currentTimeMillis() / 1000;
        String nonceStr = WStringUtil.randomSubStr(UUIDUtil.get32UUID(), 10).toUpperCase();

        PaySign paySign = new PaySign();
        paySign.setAppId(miniappProperties.getAppKey());
        paySign.setPrepayId(payPrepay.getPrepayId());
        paySign.setNonceStr(nonceStr);
        paySign.setTimestamp(String.valueOf(timestamp));
        paySign.setPaySign(getPaySign(timestamp, nonceStr, payPrepay.getPrepayId()));
        return paySign;
    }
     **/

    /**
     * 获得小程序签名
     *
     * @param timestamp
     * @param nonceStr
     * @param prepayId
     * @return
     * @throws Exception
     */
    private String getPaySign(long timestamp, String nonceStr, String prepayId) throws Exception {
        StringBuilder signBS = new StringBuilder();
        signBS.append(miniappProperties.getAppKey()).append("\n")
                .append(timestamp).append("\n")
                .append(nonceStr).append("\n")
                .append("prepay_id=").append(prepayId).append("\n");
        String key = PayPrivateKeyUtil.getPrivateKey(payProperties.getKeyFilePath());
        // 生成签名
        return PayPrivateKeyUtil.encryptByPrivateKey(signBS.toString(), key);
    }

    /**
     * 获取
     * @param payPlaceOrder
     * @return
     */
    private JSONObject getPlaceOrderJsonObject(PayPlaceOrder payPlaceOrder) {
        JSONObject bodyObject = new JSONObject();
        bodyObject.put("appid", payPlaceOrder.getAppid());
        bodyObject.put("mchid", payPlaceOrder.getMchid());
        bodyObject.put("description", payPlaceOrder.getDescription());
        bodyObject.put("out_trade_no", payPlaceOrder.getOutTradeNo());
        bodyObject.put("time_expire", payPlaceOrder.getTimeExpire());
        bodyObject.put("attach", payPlaceOrder.getAttach());
        bodyObject.put("notify_url", payPlaceOrder.getNotifyUrl());
        bodyObject.put("goods_tag", payPlaceOrder.getGoodsTag());
        bodyObject.put("amount", getAmountJsonObject(payPlaceOrder.getAmount()));
        bodyObject.put("payer", getPayer(payPlaceOrder.getPayer()));
        if (payPlaceOrder.getDetail() != null) {
            bodyObject.put("detail", getDetail(payPlaceOrder.getDetail()));
        }
        if (payPlaceOrder.getSceneInfo() != null) {
            bodyObject.put("scene_info", getSceneInfo(payPlaceOrder.getSceneInfo()));
        }
        if (payPlaceOrder.getSettleInfo() != null) {
            bodyObject.put("settle_info", getSettleInfo(payPlaceOrder.getSettleInfo()));
        }
        return bodyObject;
    }

    /**
     * 订单金额
     *
     * @param amount
     * @return
     */
    private JSONObject getAmountJsonObject(PayPlaceOrder.Amount amount) {
        JSONObject amountJsonObject = new JSONObject();
        amountJsonObject.put("total", amount.getTotal());
        amountJsonObject.put("currency", amount.getCurrency());
        return amountJsonObject;
    }

    /**
     * 支付者
     *
     * @param payer
     * @return
     */
    private JSONObject getPayer(PayPlaceOrder.Payer payer) {
        JSONObject payerJsonObject = new JSONObject();
        payerJsonObject.put("openid", payer.getOpenid());
        return payerJsonObject;
    }

    /**
     * 优惠功能
     *
     * @param detail
     * @return
     */
    private JSONObject getDetail(PayPlaceOrder.Detail detail) {
        JSONObject detailJsonObject = new JSONObject();
        detailJsonObject.put("cost_price", detail.getCostPrice());
        detailJsonObject.put("invoice_id", detail.getInvoiceId());
        if (detail.getGoodsDetail() != null || !detail.getGoodsDetail().isEmpty()) {
            detailJsonObject.put("goods_detail", listGoodsDetail(detail.getGoodsDetail()));
        }
        return detailJsonObject;
    }

    /**
     * 商品列表
     *
     * @param goodsList
     * @return
     */
    private JSONArray listGoodsDetail(List<PayPlaceOrder.Detail.Goods> goodsList) {
        JSONArray goodsDetailJsonArray = new JSONArray();
        for (PayPlaceOrder.Detail.Goods goods : goodsList) {
            JSONObject goodsJsonObject = new JSONObject();
            goodsJsonObject.put("merchant_goods_id", goods.getMerchantGoodsId());
            goodsJsonObject.put("wechatpay_goods_id", goods.getWechatpayGoodsId());
            goodsJsonObject.put("goods_name", goods.getGoodsName());
            goodsJsonObject.put("quantity", goods.getQuantity());
            goodsJsonObject.put("unit_price", goods.getUnitPrice());
            goodsDetailJsonArray.add(goodsJsonObject);
        }
        return goodsDetailJsonArray;
    }

    /**
     * 场景信息
     *
     * @param sceneInfo
     * @return
     */
    private JSONObject getSceneInfo(PayPlaceOrder.SceneInfo sceneInfo) {
        JSONObject sceneInfoJsonObject = new JSONObject();
        sceneInfoJsonObject.put("payer_client_ip", sceneInfo.getPayerClientIp());
        sceneInfoJsonObject.put("device_id", sceneInfo.getDeviceId());
        if (sceneInfo.getStoreInfo() != null) {
            sceneInfoJsonObject.put("store_info", getStoreInfo(sceneInfo.getStoreInfo()));
        }
        return sceneInfoJsonObject;
    }

    /**
     * 商户门店信息
     *
     * @param storeInfo
     * @return
     */
    private JSONObject getStoreInfo(PayPlaceOrder.SceneInfo.StoreInfo storeInfo) {
        JSONObject storeInfoJsonObject = new JSONObject();
        storeInfoJsonObject.put("id", storeInfo.getId());
        storeInfoJsonObject.put("name", storeInfo.getName());
        storeInfoJsonObject.put("area_code", storeInfo.getAreaCode());
        storeInfoJsonObject.put("address", storeInfo.getAddress());
        return storeInfoJsonObject;
    }

    /**
     * 是否指定分账
     *
     * @param settleInfo
     * @return
     */
    private JSONObject getSettleInfo(PayPlaceOrder.SettleInfo settleInfo) {
        JSONObject settleJsonObject = new JSONObject();
        settleJsonObject.put("profit_sharing", settleInfo.getProfitSharing());
        return settleJsonObject;
    }

}
