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

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bohuikeji.delivery.backstage.entity.TConfig;
import com.bohuikeji.delivery.backstage.entity.TOrder;
import com.bohuikeji.delivery.backstage.util.OrderUtils;
import com.bohuikeji.delivery.backstage.util.PhoneUtils;
import com.bohuikeji.frame.module.admin.entity.back.APIEntity;
import com.bohuikeji.frame.module.admin.entity.vo.AddressVo;
import com.bohuikeji.frame.module.admin.utils.MapUtils;
import com.bohuikeji.frame.module.admin.utils.NumberUtils;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import jodd.http.HttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

import static java.nio.charset.StandardCharsets.UTF_8;
import static jdk.nashorn.internal.objects.NativeString.toUpperCase;

/**
 * 闪送开放平台接入
 * @author Admin
 */
@Slf4j
public class ShanSongUtils {

    /**
     * 测试环境
     */
    //public static final String BASE_URL="http://open.s.bingex.com";

    /**
     * 生产环境
     */
    public static final String BASE_URL="http://open.ishansong.com";

    private static final String APP_SECRET="txpL13KrbUZJW3dsWfAx2FdkptAX3E3I";

    private static final String CLIENT_ID="ss1nFXKKAFhInIb9X";


    /**
     * 生产环境
     */
    private static final String SHOP_ID="20000000000121776";

    /**
     * 测试环境
     */
    /*private static final String SHOP_ID="20000000000001694";*/

    /**
     * 开通城市接口
     */
    private static final String QUERY_CITY=BASE_URL+"/openapi/merchants/v5/openCitiesLists";

    /**
     * 查询城市可指定交通方式
     */
    private static final String CITY_traffic=BASE_URL+"/openapi/merchants/v5/optionalTravelWay";

    /**
     * 计费查询
     */
    private static final String ORDER_QUERY_BILLING =BASE_URL+"/openapi/merchants/v5/orderCalculate";

    /**
     * 下单
     */
    private static final String ORDER_PLACE=BASE_URL+"/openapi/merchants/v5/orderPlace";

    /**
     * 订单加小费
     */
    private static final String ORDER_TIP=BASE_URL+"/openapi/developer/v5/addition";

    /**
     * 取消订单
     */
    private static final String ORDER_CANCEL=BASE_URL+"/openapi/merchants/v5/abortOrder";
    /**
     * 查询账户额度
     */
    private static final String ACCOUNT_QUERY=BASE_URL+"/openapi/merchants/v5/getUserAccount";

    /**
     * 查询订单详情
     */
    private static final String ORDER_QUERY_DETAIL=BASE_URL+"/openapi/merchants/v5/orderInfo";

    /**
     * 查询订单的配送员信息
     */
    private static final String COURIER_QUERY=BASE_URL+"/openapi/merchants/v5/courierInfo";



    /**
     * 查询开通城市
     * @return
     */
    public static APIEntity<JSONObject> QueryCity(){
        return request(QUERY_CITY,null);
    }

    /**
     * 订单询价
     * @param order
     * @return
     */
    public static APIEntity<JSONObject> orderQueryBilling(TOrder order){
        log.error("【同城急送订单号：】订单:{}",order.getOrderNum());
        JSONObject data=orderConvert(order);
        if (data==null){return APIEntity.fail("[闪送询价取消]询价订单参数缺失！");}
        log.error("【闪送询价参数：】订单:{}，参数：{}",order.getOrderNum(),data.toJSONString());
        return request(ORDER_QUERY_BILLING,data);
    }

    /**
     * 提交订单
     * @param issOrderNo 订单询价接口返回的issOrderNo单号
     * @return
     */
    public static APIEntity<JSONObject> orderPlace(String issOrderNo){
        JSONObject dat=new JSONObject();
        dat.put("issOrderNo",issOrderNo);
        return request(ORDER_PLACE,dat);
    }

    /**
     * 取消订单
     * @param issOrderNo 闪送订单号
     * @return
     */
    public static APIEntity<JSONObject> orderCancel(String issOrderNo){
        JSONObject dat=new JSONObject();
        dat.put("issOrderNo",issOrderNo);
        return request(ORDER_CANCEL,dat);
    }

    /**
     * 查询账户余额
     * @return
     */
    public static APIEntity<JSONObject> accountQuery(){
        return request(ACCOUNT_QUERY);
    }

    /**
     * 查询订单详情
     * @param issOrderNo 闪送订单号
     * @param orderNum 系统订单号
     * @return
     */
    public static APIEntity<JSONObject> orderQuery(String issOrderNo,String orderNum){
        JSONObject dat=new JSONObject();
        dat.put("issOrderNo",issOrderNo);
        dat.put("thirdOrderNo",orderNum);
        return request(ORDER_QUERY_DETAIL,dat);
    }

    /**
     * 查询订单配送员的位置
     * @param issOrderNo
     * @return
     */
    public static APIEntity<JSONObject> courierQuery(String issOrderNo){
        JSONObject dat=new JSONObject();
        dat.put("issOrderNo",issOrderNo);
        return request(COURIER_QUERY,dat);
    }


    /**
     * 闪送签名
     * @param data 数据
     * @return
     */
    private static Map<String,String> getInitParams(JSONObject data){
        Map<String,String> params=new TreeMap<>();
        params.put("clientId",CLIENT_ID);
        params.put("shopId",SHOP_ID);
        params.put("timestamp",System.currentTimeMillis()+"");
        /*params.put("appSecret",APP_SECRET);*/
        if (data!=null){
            params.put("data",data.toJSONString());
        }
        StringBuilder stringBuilder=new StringBuilder(APP_SECRET);
        params.forEach((k,v)->{
            if (StringUtils.isNotBlank(v)){
                stringBuilder.append(k);
                stringBuilder.append(v);
            }
        });
        params.put("sign",DigestUtils.md5DigestAsHex(stringBuilder.toString().getBytes(StandardCharsets.UTF_8)).toUpperCase(Locale.ROOT));
        return  params;
    }
    /**
     * 请求接口,自动签名
     * @param url 接口地址
     * @param data 业务参数
     * @return 返回接口DATA数据
     */
    private static APIEntity<JSONObject> request(String url, JSONObject data){
        String resStr= HttpRequest.post(url).query(getInitParams(data)).contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE,"UTF-8").send().bodyText();
        if (StringUtils.isBlank(resStr)){
            log.error("【闪送开放平台】接口：{},返回：{},数据信息:{}",url,resStr,data);
            throw new RuntimeException("闪送开放平台，接口未返回数据！");
        }
        JSONObject resJson=JSON.parseObject(resStr);
        if (resJson.getIntValue("status")!=200){
            log.error("【闪送开放平台异常】接口：{},返回：{}",url,resStr);
            return APIEntity.fail(resJson.getString("msg"));
            //throw new RuntimeException("闪送开放平台异常，错误信息："+resJson.getString("msg"));
        }
        return APIEntity.success(resJson.getJSONObject("data"));
    }

    /**
     * 请求无参数接口
     * @param url
     * @return
     */
    private static APIEntity<JSONObject> request(String url){
        return request(url,null);
    }

    /**
     * 订单转闪送格式
     * @param code
     * @return
     */
    public static Integer travelWay(String code){
        String cityName = code.substring(0,code.length()-2);
        JSONObject data=new JSONObject();
        data.put("cityId",Integer.valueOf(cityName));
        String resStr= HttpRequest.post(CITY_traffic).query(getInitParams(data)).contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE,"UTF-8").send().bodyText();
        JSONObject resJson=JSON.parseObject(resStr);
        JSONObject jsonObject = null;
        JSONArray array = resJson.getJSONArray("data");
        for(int i=0;i<array.size();i++) {
            if("汽车".equals(array.getJSONObject(i).getString("desc"))){
                jsonObject = array.getJSONObject(i);
            }
        }
        if(jsonObject == null){
            return null;
        }
        return jsonObject.getInteger("travelWay");
    }

    /**
     * 订单转闪送格式
     * @param order
     * @return
     */
    private static JSONObject orderConvert(TOrder order){
        AddressVo mailingAddress=order.getMailingAddress().fillAddress();
        AddressVo receiptAddress=order.getReceiptAddress().fillAddress();
        if (mailingAddress==null||receiptAddress==null){
            return null;
        }
        //List<AddressVo> addressVoList=MapUtils.gdToBd(mailingAddress,receiptAddress);
        JSONObject orderJs=new JSONObject();
        String cityName=mailingAddress.getCity();
        if (StringUtils.isBlank(cityName)||"[]".equals(cityName)){
            cityName=mailingAddress.getProvince();
        }
        if(StringUtils.isBlank(cityName)){
            return null;
        }
        if(order.getPlayerId()==203){
            orderJs.put("pickupPwd",1);
            orderJs.put("deliveryPwd",1);
        }
        orderJs.put("cityName",cityName);
        orderJs.put("travelWay",order.getTravelWay());
        orderJs.put("lbsType",1);
        JSONObject sender=new JSONObject();
        if(mailingAddress.getAddress().contains("市")){
            sender.put("fromAddress",mailingAddress.getAddress());
        }else {
            sender.put("fromAddress",mailingAddress.getCity()+mailingAddress.getAddress());
        }
        sender.put("fromAddressDetail",mailingAddress.getDetail());
        sender.put("fromSenderName",order.getMailingName());
        sender.put("fromMobile", PhoneUtils.getPhone(order.getMailingPhone()));//寄件手机号处理
        sender.put("fromLatitude", mailingAddress.getLat());
        sender.put("fromLongitude",mailingAddress.getLng());
        orderJs.put("sender",sender);
        JSONObject receiverJson=new JSONObject();
        String orderNum=order.getOrderNum();
        if(StringUtils.isBlank(orderNum)){
            orderNum=NumberUtils.getRandom(12);
            receiverJson.put("orderNo",NumberUtils.getRandom(12));
        }
        receiverJson.put("toMobile",PhoneUtils.getPhone(order.getReceiptPhone()));//收件手机号处理
        receiverJson.put("orderNo",orderNum);
        if(receiptAddress.getAddress().contains("市")){
            receiverJson.put("toAddress",receiptAddress.getAddress());
        }else {
            receiverJson.put("toAddress",mailingAddress.getCity()+receiptAddress.getAddress());
        }
        receiverJson.put("toAddressDetail",receiptAddress.getDetail());
        receiverJson.put("toLatitude",receiptAddress.getLat());
        receiverJson.put("toLongitude",receiptAddress.getLng());
        receiverJson.put("toReceiverName",order.getReceiptName());
        receiverJson.put("orderingSourceType",5);
        receiverJson.put("orderingSourceNo",orderNum);
        int goodsType=1;
        switch (order.getCargoName()){
            case "商务文件":
            case "广告印务":
                goodsType=1;break;
            case "电子产品":
                goodsType=3;break;
            case "生日蛋糕":
                goodsType=5;break;
            case "鲜花礼品":
                goodsType=7;break;
            default:
                goodsType=10;break;
        }
        receiverJson.put("goodType",goodsType);
        receiverJson.put("weight",order.getCargoWeight());
        receiverJson.put("remarks",order.getOrderRemarks());
        receiverJson.put("additionFee",0);
        LocalDateTime endTime= OrderUtils.getSurplusTime(order);
        Duration duration = Duration.between(LocalDateTime.now(),endTime);
        if(order.getInsured() && duration.toHours()<2){
            receiverJson.put("qualityDelivery",1);
            receiverJson.put("goodsPrice",new BigDecimal(order.getWorthName().replace("元","")).multiply(new BigDecimal("100")));
            log.info("保价进入这里");
        }
        JSONArray receiverListJson=new JSONArray();
        receiverListJson.add(receiverJson);
        orderJs.put("receiverList",receiverListJson);
        //取件时间大于俩小时记为预约订单
        if(duration.toHours()>=2){
            orderJs.put("appointType",1);
            orderJs.put("appointmentDate",endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
        }else {
            orderJs.put("appointType",0);
        }
        return orderJs;
    }


    /**
     * 闪送订单添加小费
     * @param thirdNum
     * @param additionAmount
     * @return
     */
    public static APIEntity<JSONObject> ssAddorderTip(String thirdNum,BigDecimal additionAmount){
        log.info("##################################顺丰订单添加小费#####################################");
        JSONObject body=new JSONObject();
        body.put("issOrderNo",thirdNum);
        body.put("additionAmount",additionAmount.multiply(new BigDecimal("100")));
        return request(ORDER_TIP,body);
    }

}
