package com.bohuikeji.delivery.backstage.util.capacity;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bohuikeji.delivery.backstage.entity.TOrder;
import com.bohuikeji.delivery.backstage.service.ITOrderService;
import com.bohuikeji.delivery.backstage.util.OrderUtils;
import com.bohuikeji.frame.module.admin.entity.vo.AddressVo;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import jodd.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.TreeMap;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * 京东配送工具类
 * @author Admin
 */
@Slf4j
public class JdUtils {

    public static final String APP_KEY="6e74308c624b43bb98316543da8959a0";
    private static final String APP_SECRET="441ab21d10ba44d4aab07a6bf4b15286";
    private static final String LOP_DN="express";
    private static final String RSA_ID="1753";
    private static final String RSA_PUBLIC="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKnS8tRt0smODwDOI/vUrYOas0ZOoBWk0giq+5XGgqxxebM9Xj+ncfbCkPxn21UcMhYmfTFLlAYGuAfHkcFA9+LezhlsS4u7Y50valIBT12L0bsFXDTjbvKMMJ4rDOWwHEUPsDgmthkIB/cbcch+gcCBWIi5USrKh0M/MeK0eZXQIDAQAB";
    /**
     * 接口授权
     */
    //private static final String ACCESS_TOKEN="1dce39181c7242549d815f639cc6690c";

    //private static final String REF_TOKEN="0d655a8621c1482392f3396f2245d0fa";

    /**
     * 新版token
     */
    private static final String ACCESS_TOKEN="9eacb62ad9164ede8c9e149bdf3efd21";

    private static final String Refresh_token="d88f51584c1b419ca30010046c9ffdd6";

    /**
     * 商家编码(旧的编码)
     */
    //private static final String CUSTOMER_CODE="010K1550148";
    /**
     * 商家编码(新的编码)
     */
    private static final String CUSTOMER_CODE="010K1946574";

    /**
     * 测试环境域名:https://test-api.jdl.cnxian
     * 线上环境域名：https://api.jdl.cn
     * 【注意】京东没有测试环境，只能使用生产环境，下单后请及时取消
     */
    private static final String BASE_URL="https://api.jdl.cn";

    /**
     * 是否可以京东配送
     */
    private static final String canJdExpressReach="/jdeliveryservicejsf/canjdexpressreach";

    /**
     * 查询预估运费和时效
     */
    private static final String queryEstimatedFreights="/query/estimatedfreights";
    /**
     * 获取运单号
     */
    private static final String preDeliveryId="/get/waybillcode";

    /**
     * 快捷下单
     */
    private static final String receiveOrderInfo="/WaybillJosService/receiveOrderInfo";

    /**
     * 普通下单
     */
    private static final String createOrder="/create/order";

    /**
     * 取消下单
     */
    private static final String cancelOrder="/OrbLsCancelWaybillInterceptService/cancelOrder";

    /**
     * 查询运费和标价
     */
    private static final String queryFeeResultByBusinessNo="/query/waybillfee";

    /**
     * 查询运单的预估运费
     */
    private static final String queryWaybillFreights="/query/waybillfreights";

    /**
     * 查询物流轨迹（商家用）
     */
    private static final String queryTrace="/TraceQueryJsf/queryTrace";

    /**
     * 获取运单实时位置
     */
    private static final String getWaybillGis="/track/queryWaybillTrack";

    /**
     * queryDynamicTraceInfo
     */
    private static final String queryDynamicTraceInfo ="/query/dynamictraceinfo";

    /**
     * 查询运单预计送达时间和扩展信息
     */
    private static final String queryOrderInfoByCondition="/generalwaybillqueryapi/queryorderinfobycondition";

    /**
     * 查询订单实际费用
     */
    private static final String queryOrderPrice="/query/waybillfee";

    @Autowired
    ITOrderService itOrderService;



    @Test
    public void test() throws Exception {
        //cancelOrder("","客户主动取消","客户");
        //TOrder order=itOrderService.getById(711);
        //queryOrderPrice("JDVA10659855408");
        /*JSONObject params=new JSONObject();
        params.put("businessNo","JDVA10975080686");
        params.put("sellerNo",CUSTOMER_CODE);*/
        System.out.println(queryOrderPrice("JDVA12171289102"));

    }


    /**
     * 确认订单是否可以使用京东配送
     * @param startAddress 发件地址
     * @param endAddress 收件地址
     * @return
     */
    public static JSONObject canJdExpressReach(String startAddress,String endAddress){
        JSONObject params=new JSONObject();
        params.put("customerCode",CUSTOMER_CODE);
        params.put("salePalt","0010003");
        params.put("goodsType","1");
        params.put("receiveAddress",endAddress);
        params.put("orderId",10244);
        params.put("senderAddress",startAddress);
        params.put("promiseTimeType",1);
        params.put("settleType",0);
        return request(canJdExpressReach,params);
    }

    /**
     * 预估订单费用和时效性
     * @param order
     *
     * LocalDateTime.now().plusMinutes(5).format(StringUtils.dataTimeFormat)
     * @return
     */
    public static JSONObject queryEstimatedFreights(TOrder order){
        JSONObject params=new JSONObject();
        params.put("senderAddress",order.getMailingAddress().getAddress());
        params.put("receiverAddress",order.getReceiptAddress().getAddress());
        Integer weight=order.getCargoWeight();
        if (weight==null||weight<1){
            weight=1;
        }
        params.put("weight",weight);
        params.put("orderTime",order.getSurplusPickTime().format(StringUtils.dataTimeFormat));
        params.put("businessType",1);
        return request(queryEstimatedFreights,params);
    }

    /**
     * 获取京东货物保费
     * @param price 货物价值
     * @return 返回保费金额，如返回null则表示无法提供保价服务
     */
    public static BigDecimal queryInsured(BigDecimal price){
        //商品价值低于0元
        if(price.compareTo(new BigDecimal("0"))<1){
            return new BigDecimal("0");
        }
        //商品价值<=500，保费1元
        if(price.compareTo(new BigDecimal("500"))<1){
            return new BigDecimal("1");
        }
        //商品价值<=1000，保费2元
        if(price.compareTo(new BigDecimal("1000"))<1){
            return new BigDecimal("2");
        }
        //商品价值<=1百万，保费5/1000元
        if(price.compareTo(new BigDecimal("1000000"))<1){
            return price.multiply(new BigDecimal("0.005")).setScale(2, RoundingMode.HALF_UP);
        }
        return null;
    }

    /**
     * 快捷下单
     * @param order 系统订单实体
     * @return
     */
    public static JSONObject receiveOrderInfo(TOrder order){
        return request(receiveOrderInfo,orderToJson(order));
    }

    /**
     * 普通下单
     * @param deliveryId
     * @param order
     * @return
     */
    public static JSONObject createOrder(String deliveryId,TOrder order){
        JSONObject params=orderToJson(order);
        params.put("deliveryId",deliveryId);
        return request(createOrder,params);
    }

    /**
     * 获取运单号
     * @param count 获取数量
     * @return
     */
    public static JSONObject preDeliveryId(Integer count){
        JSONObject params=new JSONObject();
        params.put("appKey",APP_KEY);
        params.put("customerCode",CUSTOMER_CODE);
        params.put("preNum",count);
        params.put("orderType",0);
        return request(preDeliveryId,params);
    }

    /**
     * 取消订单
     * @param deliveryId 京东订单号
     * @param interceptReason 取消原因
     * @param cancelOperator 取消操作人
     * @return
     */
    public static boolean cancelOrder(String deliveryId,String interceptReason,String cancelOperator){
        JSONObject params=new JSONObject();
        params.put("cancelTime",System.currentTimeMillis());
        params.put("vendorCode",CUSTOMER_CODE);
        params.put("deliveryId",deliveryId);
        params.put("interceptReason",interceptReason);
        params.put("cancelReasonCode",1);
        params.put("cancelOperator",cancelOperator);
        JSONObject res=request(cancelOrder,params);
        return res.getIntValue("stateCode")==1;

    }

    /**
     * 查询订单费用、体积等基础信息
     * @param deliveryId 京东运单号
     * @return
     */
    public static JSONObject queryWaybillFreights(String deliveryId){
        JSONObject params=new JSONObject();
        params.put("vendorCode",CUSTOMER_CODE);
        params.put("waybillCode",deliveryId);
        return request(queryWaybillFreights,params);
    }

    /**
     * 查询物流轨迹
     * @param deliveryId 京东运单号
     * @return
     */
    public static JSONObject queryTrace(String deliveryId){
        JSONObject params=new JSONObject();
        params.put("customerCode",CUSTOMER_CODE);
        params.put("waybillCode",deliveryId);
        params.put("josPin","");
        return request(queryTrace,params);
    }

    /**
     * 查询骑手实时信息
     * @param deliveryId 京东运单号
     * @return
     */
    public static JSONObject waybillGisTrack(String deliveryId){
        JSONObject params=new JSONObject();
        params.put("customerCode",CUSTOMER_CODE);
        params.put("waybillCode",deliveryId);
        params.put("josPin","");
        return request(getWaybillGis,params);
    }

    /**
     * 订单全程跟踪查询
     * @param deliveryId 运单号
     * @return 返回订单各个节点集合，可用于订单状态核对等
     */
    public static JSONObject queryDynamicTraceInfo(String deliveryId){
        JSONObject params=new JSONObject();
        params.put("customerCode",CUSTOMER_CODE);
        params.put("waybillCode",deliveryId);
        params.put("josPin","jd_12");
        return request(queryDynamicTraceInfo,params);
    }

    /**
     * 查询运单预计送达时间和扩展信息
     * @param deliveryId 京东运单号
     * @return
     */
    public static JSONObject queryOrderInfoByCondition(String deliveryId){
        JSONObject params=new JSONObject();
        params.put("customerCode",CUSTOMER_CODE);
        params.put("deliveryId",deliveryId);
        params.put("josPin","pin");
        return request(queryOrderInfoByCondition,params);
    }

    /**
     * 查询订单京东是实际计费
     * @param waybillCode 京东订单
     * @return
     */
    public static JSONObject queryOrderPrice(String waybillCode){
        JSONObject params=new JSONObject();
        params.put("businessNo",waybillCode);
        params.put("sellerNo",CUSTOMER_CODE);
        JSONObject res=request(queryOrderPrice,params);
        return res;
    }


    /**
     * 发送请求
     * @param method
     * @param params
     * @return
     */
    private static JSONObject request(String method,JSONObject params){
        Map<String,String> map=new TreeMap<>();
        map.put("method",method);
        map.put("timestamp", LocalDateTime.now().format(StringUtils.dataTimeFormat));
        map.put("v","2.0");
        map.put("access_token",ACCESS_TOKEN);
        map.put("app_key",APP_KEY);
        map.put("param_json","["+params.toJSONString()+"]");
        map.put("sign",sign(map));
        map.put("LOP-DN",LOP_DN);
        HttpRequest req=HttpRequest.post(BASE_URL+method)
                .bodyText(map.get("param_json"), MediaType.APPLICATION_JSON_VALUE,"UTF-8")
                .contentType(MediaType.APPLICATION_JSON_VALUE,"UTF-8");
        map.remove("param_json");
        //发送请求
        String res=req.query(map).send().bodyText();
       /* log.error("res={}",res);
        log.error("【京东接口调用】：请求接口：{}",method);
        log.error("【京东接口调用】：请求参数：{}",params.toJSONString());
        log.error("【京东接口调用】：返回值：{}",res);
        log.error("===========================================");*/
        return JSON.parseObject(res);
    }


    /**
     *  签名
     * @return
     */
    private static String sign(Map<String,String> map){
        StringBuilder str=new StringBuilder();
        str.append(APP_SECRET);
        map.forEach((k,v)->{
            str.append(k);
            str.append(v);
        });
        str.append(APP_SECRET);
        String sign= null;
        try {
            sign = md5Hex(str.toString());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return sign;
    }

    /**
     * 计算MD5值
     * @param string
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String md5Hex(String string) throws NoSuchAlgorithmException {
        StringBuilder md5Hex = new StringBuilder();
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        for (byte b : md5.digest(string.getBytes(UTF_8))) {
            md5Hex.append(String.format("%02X", b));
        }
        return md5Hex.toString();
    }

    /**
     * 转换订单
     * @param order
     * @return
     */
    private  static JSONObject orderToJson(TOrder order){
        JSONObject params=new JSONObject();
        params.put("josPin ",null);
        params.put("appKey",APP_KEY);
        params.put("salePlat","0030001");
        params.put("customerCode",CUSTOMER_CODE);
        params.put("orderId",order.getOrderNum());
        params.put("senderName",order.getMailingName());
        AddressVo maAddress=order.getMailingAddress();
        params.put("senderAddress",maAddress.getAddress()+maAddress.getDetail());
        params.put("senderMobile",order.getMailingPhone());
        params.put("receiveName",order.getReceiptName());
        AddressVo reAddress=order.getReceiptAddress();
        params.put("receiveAddress",reAddress.getAddress()+reAddress.getDetail());
        params.put("receiveMobile",order.getReceiptPhone());
        params.put("pickMethod","上门收货");
        LocalDateTime[] times= OrderUtils.getOrSurplusTimeArea(order.getPickTime());
        params.put("pickUpStartTime",times[0].format(StringUtils.dataTimeFormat));
        params.put("pickUpEndTime",times[1].format(StringUtils.dataTimeFormat));
        params.put("packageCount",order.getPackageCount());
        params.put("weight",order.getCargoWeight());
        params.put("vloumn",0);
        params.put("description",order.getCargoName());
        params.put("goodsMoney",order.getWorthName().replace("元",""));
        params.put("remark",order.getOrderRemarks());
        params.put("promiseTimeType",JdUtils.getPromiseTimeType(order.getPromiseTimeType()));
        params.put("addedService","settleType:0");
        if (order.getInsured()){
            params.put("guaranteeValue",1);
            params.put("guaranteeValueAmount",params.getString("goodsMoney"));
        }
        return params;
    }

    public static Integer getPromiseTimeType(String promiseTimeType){
        Integer type=1;
        if(StringUtils.isBlank(promiseTimeType)){
            return type;
        }
        switch (promiseTimeType){
            case "普通配送":
                type=1;break;
            case "特快送":
                type=2;break;
            case "城际闪送":
                type=4;break;
            case "微小件":
                type=7;break;
            case "生鲜特快":
                type=16;break;
            case "生鲜配送":
                type=17;break;
            case "函速达":
                type=20;break;
            case "特惠包裹":
                type=21;break;
            case "医药冷链":
                type=22;break;
            case "特惠小件":
                type=24;break;
            default:
                return null;
        }
        return type;
    }
}
