package ink.wgink.module.wechat.request.pay.v3.jsapi;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import ink.wgink.exceptions.base.SystemException;
import ink.wgink.module.wechat.pojo.pay.v3.PayErrorResponse;
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.request.pay.v3.AbstractPayRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.HttpClientErrorException;

import java.util.List;

/**
 * @ClassName: PlaceOrderPayRequest
 * @Description: 下单请求
 * @Author: wanggeng
 * @Date: 2021/8/19 3:22 下午
 * @Version: 1.0
 */
public class PlaceOrderPayRequestImpl extends AbstractPayRequest<PayPlaceOrder, JSONObject, PayPrepay> {

    @Override
    public JSONObject bodyJson(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;
    }

    @Override
    public PayPrepay response(ResponseEntity<String> responseEntity) {
        LOG.debug("Response success status code: {}", responseEntity.getStatusCode());
        if (responseEntity.getStatusCode() == HttpStatus.OK) {
            return JSONObject.parseObject(responseEntity.getBody(), PayPrepay.class);
        }
        return null;
    }

    @Override
    public void error(HttpClientErrorException e) {
        LOG.debug("Response error status code：{}", e.getStatusCode());
        PayErrorResponse payErrorResponse = JSONObject.parseObject(e.getResponseBodyAsString(), PayErrorResponse.class);
        LOG.debug("Response error detail: {}", payErrorResponse.getDetail());
        throw new SystemException(payErrorResponse.getMessage());
    }

    /**
     * 订单金额
     *
     * @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;
    }

}
