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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bohuikeji.delivery.backstage.entity.TOrder;
import com.bohuikeji.frame.module.admin.entity.back.APIEntity;
import com.bohuikeji.frame.module.admin.entity.vo.AddressVo;
import com.bohuikeji.frame.module.admin.service.ISysConfigService;
import com.bohuikeji.frame.module.admin.utils.GCJ2WGSUtils;
import com.bohuikeji.frame.module.admin.utils.Huolala.HuolalaSignUtils;
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 jodd.net.MimeTypes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * 货拉拉工具类
 */
@Slf4j
public class HllUtils {
    @Autowired
    ISysConfigService configService;
    //沙箱环境
   /* public static final String app_key="3PJowh1YmrcpBBrflpmMUobwXIv7075S";
    public static final String app_secret="VRkv1hyjg4XIPxwQwM8iQWJVi4Ei4Rv7";
    public static final String formal_url="https://openapi-pre.huolala.cn/v1";//沙箱环境服务入口
    public static final String notify_url="https://test.tcjskd.com/delivery/api/callback/hll/order/notice";//下单回调地址*/


    //正式环境
    public static final String app_key="eJg7ZrrHLHzB9T8n9IxxsDc2qn2lUoBf";
    public static final String app_secret="viFvMMJ2TnFQeH7MHhAMSdISwucn9bAE";
    public static final String notify_url="https://os.tcjskd.com/delivery/api/callback/hll/order/notice";//下单回调地址
    public static final String formal_url="https://openapi.huolala.cn/v1";//生产环境服务入口

    /**
     * 公共请求参数
     * @param method
     * @param token
     * @return
     */
    public static Map<String,Object> getMap(String method,String token){
        Map<String,Object> map=new TreeMap<>();
        map.put("api_method",method);
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));//UUID.randomUUID().toString().replace("-", "")
        return map;
    }

    /**
     * 货拉拉网络请求
     * @param req
     * @return
     */
    private static JSONObject getDataJson(String req){
        String resultJson = HttpRequest.post(formal_url).bodyText(req,MimeTypes.MIME_APPLICATION_JSON,"UTF-8").send()
                .contentType("application/json","utf-8").bodyText();
        return JSONObject.parseObject(resultJson);
    }

    /**
     * 已开通城市列表
     * @return
     */
    public static JSONObject getEcityList(){
        Map<String,Object> map= HllUtils.getMap("e-city-list",null);
        map.put("signature", HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res;
    }


    /**
     * 城市可选车型及增值服务
     * @return
     */
    public static JSONObject getEcityInfo(Integer cityId){
        Map<String,Object> map= HllUtils.getMap("e-city-info",null);
        map.put("city_id",cityId);
        map.put("signature", HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res.getJSONObject("data");
    }

    /**
     * 地址检索(新)
     * @return
     */
    public static JSONArray getECitySearch(String token,String kw,String city){
        Map<String,Object> map= HllUtils.getMap("e-city-search",token);
        map.put("kw",kw);
        map.put("city",city);
        map.put("signature", HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res.getJSONObject("data").getJSONArray("poi");
    }

    /**
     * 订单计价（新）
     * @return
     */
    public static JSONObject getEpriceCalculate(TOrder order){
        JSONObject cityServices = HllUtils.getEcityVehicle(order);
        int[] arr = HllUtils.getEcityspecReqArr(order);
        Map<String,Object> map= HllUtils.getMap("e-price-calculate",order.getHuoToken());
        map.put("city_id", order.getCityId());
        map.put("order_vehicle_id",cityServices.getString("orderVehicleId"));//车辆id//HllUtils.getEcityInfo().getJSONObject("data").getJSONArray("vehicle_arr").getJSONObject(0).getString("order_vehicle_id")
        map.put("spec_req_arr","\""+arr+"\"");//订单额外服务
        map.put("city_info_revision",cityServices.getString("revision"));//版本号
        map.put("lat_lon_arr", String.valueOf(HllUtils.getPriceJSONArray(order)));//订单取送地址
        map.put("signature", HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res.getJSONObject("data");
    }

    /**
     * 选址下单
     * @param order
     * @return
     *
     */
    public static JSONObject getEorderRequest(TOrder order){
        JSONObject hulalaPrice= getEpriceCalculate(order);
        log.info("货拉拉估价id：{}",hulalaPrice.getLongValue("price_calculate_id"));
        JSONObject cityServices = HllUtils.getEcityVehicle(order);
        int[] arr = HllUtils.getEcityspecReqArr(order);
        Map<String,Object> map= HllUtils.getMap("e-order-request",order.getHuoToken());
        map.put("city_id", order.getCityId());
        map.put("order_vehicle_id",cityServices.getInteger("orderVehicleId"));//车辆id
        map.put("spec_req_arr","\""+arr+"\"");//订单额外服务
        map.put("addr_info", String.valueOf(HllUtils.getOrderJSONArray(order)));//订单取送地址
        map.put("order_time", order.getSurplusPickTime().toEpochSecond(ZoneOffset.of("+8")));
        map.put("total_price_fen",order.getThirdPrice().multiply(new BigDecimal("100")).floatValue());//order.getOrderExpectPrice().multiply(new BigDecimal("100")).floatValue()
        map.put("city_info_revision",cityServices.getInteger("revision"));//版本号
        map.put("contact_name", order.getMailingName());
        map.put("contact_phone_no",order.getMailingPhone());
        map.put("remark", order.getOrderRemarks());
        map.put("notify_url", notify_url);
        map.put("outside_order_id", order.getOrderNum());
        map.put("price_calculate_id",hulalaPrice.getLongValue("price_calculate_id"));
        map.put("pay_type",3);
        map.put("signature", HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        log.info("货拉拉下单结果返回：{}",res);
        return res;
    }

    /**
     * 确认账单
     * 当运输任务完成后,司机会发送账单,此账单需下单用户确认,如果产生了额外费用需支付额外费用。
     * @param order
     * @return
     *
     */
    public static JSONObject getEorderConfirm(String thirdNum){
        Map<String,Object> map= HllUtils.getMap("e-order-confirm","qAWSklm1dcK29mEChfbDCUUSNx6NA7Ed");
        map.put("order_display_id", thirdNum);
        map.put("signature", HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        log.info("货拉拉下单结果返回：{}",res);
        return res;
    }


    /**
     *  优惠券列表
     * @return
     */
    public static JSONObject getEcouponList(String token){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type",1);
        Map<String,Object> map= new HashMap<>();
        map.put("api_method","e-coupon-list");
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));
        map.put("api_data",String.valueOf(jsonObject));
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res;
    }

    /**
     * 订单详情 需用户授权
     * @param token
     * @param orderDisplayid
     * @return
     */
    public static JSONObject getEOrderDetail(String token,String orderDisplayid){
        Map<String,Object> map= new HashMap<>();
        map.put("api_method","e-order-detail");
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));
        map.put("order_display_id",orderDisplayid);
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        if(!"success".equals(res.getString("msg"))){
            log.error("货拉拉获取订单详情错误信息：{}",res);
            return null;
        }
        return res.getJSONObject("data").getJSONObject("order_detail_item").getJSONObject("order_item");
    }

    /**
     * 获取骑手信息
     * @param token
     * @param orderDisplayid
     * @return
     */
    public static JSONObject getCureierDetail(String token,String orderDisplayid){
        Map<String,Object> map= new HashMap<>();
        map.put("api_method","e-order-detail");
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));
        map.put("order_display_id",orderDisplayid);
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res;
    }

    /**
     * 订单详情 获取后置收费明细
     * @param token
     * @param orderDisplayid
     * @return
     */
    public static JSONArray getEOrderDetailtwo(String token,String orderDisplayid){
        log.info("货拉拉token：{}，货拉拉订单号：{}",token,orderDisplayid);
        Map<String,Object> map= new HashMap<>();
        map.put("api_method","e-order-detail");
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));
        map.put("order_display_id",orderDisplayid);
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res.getJSONObject("data").getJSONObject("order_detail_item").getJSONArray("bill_price_arr");
    }

    /**
     * 取消订单
     * @param token
     * @param status
     * @param displayid
     * @return
     */
    public static JSONObject getEOrderCancel(String token,String status,String displayid){
        Map<String,Object> map= new HashMap<>();
        map.put("api_method","e-order-cancel");
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));
        map.put("order_display_id",displayid);
        map.put("order_status",status);
        map.put("reason","计划有变，暂时不需要用车");
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res;
    }

    /**
     * 货拉拉订单添加小费
     * @param token
     * @param displayid
     * @param tipsFen
     * @return
     */
    public static JSONObject hllAddorderTip(String token,String displayid,BigDecimal tipsFen){
        Map<String,Object> map= HllUtils.getMap("e-order-add-tips",token);
        map.put("order_display_id",displayid);
        map.put("tips_fen",tipsFen);
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        JSONObject res= HllUtils.getDataJson(req);
        return res;
    }

    /**
     * 取消原因
     * @param token
     * @param type
     * @param displayid
     * @return
     */
    /*public static JSONObject getEOrderCancelReason(String token,String type,String displayid){
        Map<String,Object> map= new HashMap<>();
        map.put("api_method","e-order-cancel-reason");
        map.put("api_version","1.0");
        map.put("app_key",app_key);
        map.put("access_token",token);
        map.put("timestamp", String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        map.put("nonce_str", NumberUtils.getRandom(3));
        map.put("order_display_id",displayid);
        map.put("type",type);
        map.put("signature",HuolalaSignUtils.getSignToken(map,app_secret));
        String req = JSONObject.toJSONString(map);
        String resultJson = HttpRequest.post(sandbox_url).bodyText(req,MimeTypes.MIME_APPLICATION_JSON,"UTF-8").send()
                .contentType("application/json","utf-8").bodyText();
        log.info("货拉拉取消订单请求返回的数据：{}",JSON.parseObject(resultJson));
        return JSON.parseObject(resultJson);
    }*/


    /**
     * 获取授权URL
     *
     * @param redirectUri 获取code的重定向跳转地址
     * @return 返回授权url
     */
    public static String getAuthURL(String redirectUri) {
        String oauthCodeUrl = String.format("https://open.huolala.cn/#/oauth/authorize?");
        String decodeRedirectUri;
        try {
            decodeRedirectUri = URLDecoder.decode(redirectUri, "UTF-8");
            return String.format("%sresponse_type=code&client_id=%s&redirect_uri=%s&isSandbox=false", oauthCodeUrl,
                    app_key, URLEncoder.encode(decodeRedirectUri, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     * 获取、刷新Token
     */
    public static JSONObject getaccessToken(String code,String refreshToken){
        Map<String, String> data = new HashMap<>();
        if(StringUtils.isNotBlank(code)){//获取token
            data.put("grant_type", "authorization_code");
            data.put("client_id",app_key);
            data.put("code",code);
            data.put("isSandbox","false");
        }else {//刷新tiken
            data.put("grant_type", "refresh_token");
            data.put("client_id", app_key);
            data.put("refresh_token", refreshToken);
            data.put("isSandbox","false");
        }
        String resultJson = HttpRequest.get("https://open.huolala.cn/oauth/token").query(data).send().contentType("application/json","utf-8").bodyText();
        JSONObject res= JSONObject.parseObject(resultJson);
        return res;
    }



    /**
     * 订单计价地址经纬度参数
     * @param order
     * @return
     */
    public static JSONArray getPriceJSONArray(TOrder order){
        JSONArray arry = new JSONArray();
        JSONObject jsonObject1 = new JSONObject(true);
        if(order.getMailingAddress() != null){
            JSONObject addJson = GCJ2WGSUtils.gcstoWGSLat(Double.parseDouble(order.getMailingAddress().getLat()),Double.parseDouble(order.getMailingAddress().getLng()));
            jsonObject1.put("lat",addJson.getDouble("lat"));
            jsonObject1.put("lon",addJson.getDouble("lon"));
            jsonObject1.put("city_id",order.getCityId());//HllUtils.getAddressCityId(order.getMailingAddress())
        }
        JSONObject jsonObject2 = new JSONObject(true);
        if(order.getReceiptAddress() != null){
            JSONObject addJson = GCJ2WGSUtils.gcstoWGSLat(Double.parseDouble(order.getReceiptAddress().getLat()),Double.parseDouble(order.getReceiptAddress().getLng()));
            jsonObject2.put("lat",addJson.getDouble("lat"));
            jsonObject2.put("lon",addJson.getDouble("lon"));
            jsonObject2.put("city_id",order.getCityId());//HllUtils.getAddressCityId(order.getReceiptAddress())
        }
        arry.add(jsonObject1);
        arry.add(jsonObject2);
        return arry;
    }

    /**
     * 选址下单经纬度参数
     * @param order
     * @return
     */
    public static String getOrderJSONArray(TOrder order){
        JSONArray arry = new JSONArray();
        JSONObject mailing = new JSONObject(true);
        if(order.getMailingAddress() != null){
            JSONObject addJson = GCJ2WGSUtils.gcstoWGSLat(Double.parseDouble(order.getMailingAddress().getLat()),Double.parseDouble(order.getMailingAddress().getLng()));
            JSONObject jsonObject1 = new JSONObject(true);
            jsonObject1.put("lat",addJson.getDouble("lat"));
            jsonObject1.put("lon",addJson.getDouble("lon"));
            mailing.put("lat_lon",jsonObject1);
            mailing.put("name",order.getMailingAddress().getArea());
            mailing.put("addr",order.getMailingAddress().getDetail());
            mailing.put("city_id",order.getCityId());//HllUtils.getAddressCityId(order.getMailingAddress())
            mailing.put("contact_name",order.getMailingName());
            mailing.put("contact_phone_no",order.getMailingPhone());
        }
        JSONObject toAdd = new JSONObject(true);
        if(order.getReceiptAddress() != null){
            JSONObject addJson = GCJ2WGSUtils.gcstoWGSLat(Double.parseDouble(order.getReceiptAddress().getLat()),Double.parseDouble(order.getReceiptAddress().getLng()));
            JSONObject jsonObject2 = new JSONObject(true);
            jsonObject2.put("lat",addJson.getDouble("lat"));
            jsonObject2.put("lon",addJson.getDouble("lon"));
            toAdd.put("lat_lon",jsonObject2);
            toAdd.put("name",order.getReceiptAddress().getArea());
            toAdd.put("addr",order.getReceiptAddress().getDetail());
            toAdd.put("city_id",order.getCityId());//HllUtils.getAddressCityId(order.getReceiptAddress())
            toAdd.put("contact_name",order.getReceiptName());
            toAdd.put("contact_phone_no",order.getReceiptPhone());
        }
        arry.add(mailing);
        arry.add(toAdd);
        //log.info("【选址下单经纬度参数】：{}",arry);
        return arry.toString();
    }

    /**
     * 获取下单人所属城市Id
     */
    public static Integer getCityId(String location){
        if(StringUtils.isBlank(location)){
            return null;
        }
        JSONArray array = HllUtils.getEcityList().getJSONArray("data");
        JSONObject jsonObject = null;
        AddressVo address = MapUtils.getAddressReGeo(location);
        String cityName = address.getCity().substring(0,address.getCity().length()-1);
        for(int i=0;i<array.size();i++) {
            if(cityName.equals(array.getJSONObject(i).getString("name"))){
                jsonObject = array.getJSONObject(i);
            }
        }
        if(jsonObject ==null){
            return null;
        }
        log.error("货拉拉获取下单人城市id:{}",jsonObject);
        return jsonObject.getInteger("city_id");
    }

    /**
     * 获取城市对应车辆和版本号
     * @return
     */
    public static JSONObject getEcityVehicle(TOrder order){
        JSONObject jsonObject = null;
        JSONObject orderJson = new JSONObject();
        JSONObject resultJson = HllUtils.getEcityInfo(order.getCityId());
        if(resultJson == null){
            return jsonObject;
        }
        String typeName = null;
        if("van".equals(order.getTravelType())){
            typeName = "中面";
        }
        if("truck".equals(order.getTravelType())){
            typeName = "中货";
        }
        if("car".equals(order.getTravelType())){
            typeName = "微面";
        }
        JSONArray array = resultJson.getJSONArray("vehicle_arr");
        for(int i=0;i<array.size();i++) {
            if(typeName.equals(array.getJSONObject(i).getString("name"))){
                jsonObject = array.getJSONObject(i);
            }
        }
        if(jsonObject == null){
            return jsonObject;
        }
        orderJson.put("revision",resultJson.getInteger("revision"));
        orderJson.put("orderVehicleId",jsonObject.getInteger("order_vehicle_id"));
        return orderJson;
    }

    /**
     *
     * 订单额外服务
     * @return
     */
    public static int[] getEcityspecReqArr(TOrder order){
        JSONObject resultJson = HllUtils.getEcityInfo(order.getCityId());
        int[] types;
        JSONObject jsonObject = null;
        if("帮助搬运".equals(order.getCarryName())){
            JSONArray array = resultJson.getJSONArray("spec_req_arr");
            for(int i=0;i<array.size();i++) {
                if("搬运".equals(array.getJSONObject(i).getString("name"))){
                    jsonObject = array.getJSONObject(i);
                }
            }
            types = new int[]{jsonObject.getInteger("type")};
        }else {
            types = new int[]{};
        }
        log.info("【###########订单额外服务###########】：车辆:{},服务:{}",order.getVehicleName(),types);
        return types;
    }
}
