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.util.OrderUtils;
import com.bohuikeji.frame.module.admin.entity.vo.AddressVo;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import jodd.http.HttpRequest;
import jodd.net.MimeTypes;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Base64;
import java.util.StringJoiner;

/**
 * 顺丰同城急送工具类
 * @author Admin
 */
@Slf4j
public class SFCityUtils {

    //测试环境
    /*public static String APP_ID="1609346351";//开发者id
    public static String COM_ID="11312143301";//企业id
    public static String APP_SECRET="b8695be61eacdd07428fa25accedb3fc";//密钥
    private static String BASE_HOST="https://openic.sf-express.com";//顺分接口域名*/

    //生产环境
    public static String APP_ID="1612122529";//开发者id
    public static String COM_ID="11312143301";//企业id
    public static String APP_SECRET="5ba5b684dfea17bb82790774a1949d07";//密钥
    private static String BASE_HOST="https://openic.sf-express.com";//顺分接口域名


    /**
     * 预创建订单
     */
    public static String URL_ORDER_READY=BASE_HOST+"/open/api/external/precreateorder4c";

    /**
     * 创建订单
     */
    public static String URL_ORDER_ESTA=BASE_HOST+"/open/api/external/createorder4c";

    /**
     * 订单加小费接口
     */
    public static String URL_ORDER_TIP=BASE_HOST+"/open/api/external/addordergratuityfee";
    /**
     * 订单加小费接口
     */
    public static String URL_GET_TIP=BASE_HOST+"/open/api/external/getordergratuityfee";

    /**
     * 修改订单
     */
    public static String URL_UPDATE_CREATE=BASE_HOST+"/open/api/external/changeorder";

    /**
     * 取消订单
     */
    public static String URL_ORDER_CANCEL=BASE_HOST+"/open/api/external/cancelorder";

    /**
     * 预取消订单
     */
    public static String URL_ORDER_CANCEL_READY=BASE_HOST+"/open/api/external/precancelorder";

    /**
     * 获取账户余额
     */
    public static String URL_ACCOUNT_BALANCE=BASE_HOST+"/open/api/external/getshopaccountbalance";

    /**
     * 订单实时信息查询
     */
    public static String URL_ORDER_DETAIL=BASE_HOST+"/open/api/external/getorderstatus";

    /**
     * 订单状态流查询
     */
    public static String  URL_ORDER_STATUS=BASE_HOST+"/open/api/external/listorderfeed";

    /**
     * 获取配送员实时坐标接口
     */
    public static String COURIER_LOCATION=BASE_HOST+"/open/api/external/riderlatestposition";

    /**
     * 预创建订单（企业用户）
     * @return
     */
    public static JSONObject orderEstimate(TOrder order){
        log.info("##################################顺丰预创建订单#####################################");
        AddressVo maAddress=order.getMailingAddress();
        AddressVo receiptAddress=order.getReceiptAddress();
        Integer weight=order.getCargoWeight();
        if (weight==null||weight.compareTo(0)<1){
            weight=1;
        }
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("settlement_type",4);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        body.put("company_id",COM_ID);
        body.put("city_name",maAddress.getCity());
        body.put("account_phone","18347923617");
        LocalDateTime endTime= getSurplusTime(order.getPickTime());
        Duration duration = Duration.between(LocalDateTime.now(),endTime);
        //取件时间大于俩小时记为预约订单
        if(duration.toHours()>=2){
            body.put("is_appoint",1);
            body.put("appoint_type",2);
            body.put("expect_pickup_time",getSurplusTime(order.getPickTime()));
        }else {
            body.put("is_appoint",0);
        }
        JSONObject sender=new JSONObject();
        sender.put("sender_name",order.getMailingName());
        sender.put("sender_phone",order.getMailingPhone());
        sender.put("sender_address",maAddress.getAddress());
        sender.put("sender_lng",maAddress.getLng());
        sender.put("sender_lat",maAddress.getLat());
        JSONObject receiver=new JSONObject();
        receiver.put("receiver_name",order.getReceiptName());
        receiver.put("receiver_phone",order.getReceiptPhone());
        receiver.put("receiver_address",receiptAddress.getAddress());
        receiver.put("receiver_lng",receiptAddress.getLng());
        receiver.put("receiver_lat",receiptAddress.getLat());
        JSONObject orderDetail=new JSONObject();
        orderDetail.put("total_price",order.getOrderExpectPrice().multiply(new BigDecimal("100")).floatValue());
        orderDetail.put("product_type", getType(order.getCargoName()));
        orderDetail.put("weight_gram",weight);
        body.put("sender",sender);
        body.put("receiver",receiver);
        body.put("order_detail",orderDetail);
        body.put("is_insured",1);
        body.put("declared_value",new BigDecimal(order.getWorthName().replace("元","")).multiply(new BigDecimal("100")));
        JSONObject res=request(URL_ORDER_READY,body);
        return res;
    }

    /**
     * 创建订单（企业用户）
     * @param order
     * @return
     */
    public static JSONObject establishOrder(TOrder order){
        AddressVo maAddress=order.getMailingAddress();
        AddressVo receiptAddress=order.getReceiptAddress();
        Integer weight=order.getCargoWeight();
        if (weight==null||weight.compareTo(0)<1){
            weight=1;
        }
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        body.put("settlement_type",1);
        body.put("user_order_id",order.getOrderNum());
        body.put("company_id",COM_ID);
        body.put("city_name",maAddress.getCity());
        body.put("account_phone","18347923617");
        LocalDateTime endTime= getSurplusTime(order.getPickTime());
        Duration duration = Duration.between(LocalDateTime.now(),endTime);
        //取件时间大于俩小时记为预约订单
        if(duration.toHours()>=2){
            body.put("is_appoint",1);
            body.put("appoint_type",2);
            body.put("expect_pickup_time",getSurplusTime(order.getPickTime()));
        }else {
            body.put("is_appoint",0);
        }
        JSONObject sender=new JSONObject();
        sender.put("sender_name",order.getMailingName());
        sender.put("sender_phone",order.getMailingPhone());
        sender.put("sender_address",maAddress.getAddress());
        sender.put("sender_lng",maAddress.getLng());
        sender.put("sender_lat",maAddress.getLat());
        JSONObject receiver=new JSONObject();
        receiver.put("receiver_name",order.getReceiptName());
        receiver.put("receiver_phone",order.getReceiptPhone());
        receiver.put("receiver_address",receiptAddress.getAddress());
        receiver.put("receiver_lng",receiptAddress.getLng());
        receiver.put("receiver_lat",receiptAddress.getLat());
        JSONObject orderDetail=new JSONObject();
        orderDetail.put("total_price",new BigDecimal(order.getWorthName().replace("元","")).multiply(new BigDecimal("100")));
        orderDetail.put("product_type", getType(order.getCargoName()));
        orderDetail.put("weight_gram",weight.intValue()*1000);
        body.put("sender",sender);
        body.put("receiver",receiver);
        body.put("order_detail",orderDetail);
        if(StringUtils.isNotBlank(order.getOrderRemarks())){
            body.put("remark",order.getOrderRemarks()+","+"如寄件人无法联系，请拨打"+order.getContactPhone());
        }else {
            body.put("remark","如寄件人无法联系，请拨打"+order.getContactPhone());
        }
        if(order.getInsured()){
            body.put("is_insured",1);
            body.put("declared_value",new BigDecimal(order.getWorthName().replace("元","")).multiply(new BigDecimal("100")));
        }else {
            body.put("is_insured",0);
        }
        JSONObject res=request(URL_ORDER_ESTA,body);
        return res;
    }


    /**
     * 顺丰订单添加小费
     * @param thirdNum
     * @param gratuityFee
     * @return
     */
    public static JSONObject sfAddorderTip(String thirdNum,BigDecimal gratuityFee){
        log.info("##################################顺丰订单添加小费#####################################");
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",thirdNum);
        body.put("gratuity_fee",gratuityFee.multiply(new BigDecimal("100")));
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        JSONObject res=request(URL_ORDER_TIP,body);
        log.info("顺丰添加小费返回结果信息：{}",res);
        return res;
    }

    /**
     * 顺丰订单添加小费
     * @param thirdNum
     * @param gratuityFee
     * @return
     */
    public static JSONObject getSforderTip(String thirdNum){
        log.info("##################################获取顺丰订单加小费信息#####################################");
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",thirdNum);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        JSONObject res=request(URL_GET_TIP,body);
        return res;
    }


    /**
     * 修改订单（企业用户）
     * @param order
     * @return
     */
    public static JSONObject updateOrder(TOrder order){
        log.info("##################################顺丰修改订单#####################################");
        log.info("订单信息：{}",order);
        AddressVo maAddress=order.getMailingAddress();
        AddressVo receiptAddress=order.getReceiptAddress();
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",order.getThirdNum());
        body.put("order_type",APP_ID);
        body.put("shop_id","3265255864945");
        body.put("shop_type",2);
        body.put("user_name",order.getReceiptName());
        body.put("user_phone",order.getReceiptPhone());
        body.put("user_address",receiptAddress.getAddress());
        body.put("user_lng",receiptAddress.getLng());
        body.put("user_lat",receiptAddress.getLat());
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        body.put("remark",order.getOrderRemarks());
        JSONObject res=request(URL_UPDATE_CREATE,body);
        return res;
    }


    /**
     * 顺丰取消订单
     * @param thirdNum
     * @return
     */
    public static JSONObject sfCancelOrder(String thirdNum){
        log.info("##################################顺丰取消订单#####################################");
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",thirdNum);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        JSONObject res=request(URL_ORDER_CANCEL,body);
        return res;
    }

    /**
     * 订单状态流查询
     * @param thirdNum
     * @return
     */
    public static JSONObject sfListorderFeed(String thirdNum){
        log.info("##################################顺丰订单状态流转#####################################");
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",thirdNum);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        JSONObject res=request(URL_ORDER_STATUS,body);
        return res;
    }

    /**
     * 订单实时信息查询
     * @param thirdNum
     * @return
     */
    public static JSONObject getSfOrderStatus(String thirdNum){
        log.info("##################################顺丰订单实时信息查询#####################################");
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",thirdNum);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        JSONObject res=request(URL_ORDER_DETAIL,body);
        return res;
    }

    /**
     * 获取配送员实时坐标接口
     * @param thirdNum
     * @return
     */
    public static JSONObject getSfCourierInfo(String thirdNum){
        log.info("##################################获取配送员实时坐标接口#####################################");
        JSONObject body=new JSONObject();
        body.put("dev_id",APP_ID);
        body.put("order_id",thirdNum);
        body.put("push_time",String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"))));
        JSONObject res=request(COURIER_LOCATION,body);
        return res;
    }


    /**
     * 签名
     * @param body 代签名的请求BODY
     * @return
     */
    private static String sign(String body){
        StringJoiner stringJoiner=new StringJoiner("&");
        stringJoiner.add(body);
        stringJoiner.add(APP_ID);
        stringJoiner.add(APP_SECRET);
        String str=stringJoiner.toString();
        //计算签名并返回
        return Base64.getEncoder().encodeToString(DigestUtils.md5DigestAsHex(str.getBytes(StandardCharsets.UTF_8)).getBytes(StandardCharsets.UTF_8));
    }

    /**
     * 请求接口,自动签名
     * @param url 接口地址
     * @param body 参数json
     * @return
     */
    public static JSONObject request(String url,JSONObject body){
        String bodyStr=body.toJSONString();
        String resStr1= HttpRequest.post(url+"?sign="+sign(bodyStr)).contentType(MediaType.APPLICATION_FORM_URLENCODED_VALUE,"UTF-8").send().bodyText();
        String resStr=HttpRequest.post(url+"?sign="+sign(bodyStr)).bodyText(bodyStr, MimeTypes.MIME_APPLICATION_JSON, "UTF-8").send()
                .contentType("application/json","utf-8").bodyText();
        log.error("【顺丰开放平台接口异常】接口：{},返回：{}，参数：{}",url,resStr1,bodyStr);
        if (StringUtils.isBlank(resStr)){
            log.error("【顺丰开放平台接口异常】接口：{},返回：{}，参数：{}",url,resStr,bodyStr);
            throw new RuntimeException("顺丰开放平台接口异常，接口未返回数据！");
        }
        return JSON.parseObject(resStr);
    }

    /**
     * 业务、优惠支付生成预支付订单参数处理
     * @return
     */
    public static Integer getType(String type) {
        Integer typeId;
        switch (type){
            case "商务文件":
                typeId=12;break;
            case "食品药品":
                typeId=2;break;
            case "生鲜水果":
                typeId=22;break;
            case "生日蛋糕":
                typeId=13;break;
            case "鲜花礼品":
                typeId=14;break;
            case "电子产品":
                typeId=15;break;
            case "生活用品":
                typeId=3;break;
            case "奢饰品化妆品":
                typeId=57;break;
            case "其他":
                typeId=99;break;
            default:
                return null;
        }
        return typeId;
    }

    public static LocalDateTime getSurplusTime(String pickTime) {
        String orderPickStr=pickTime;
        LocalDateTime now=LocalDateTime.now().plusMinutes(5);
        if("今天/2小时内".equals(orderPickStr)){
            return now.plusHours(2);
        }
        if("今天/一小时内".equals(orderPickStr)){
            return now.plusHours(1);
        }
        if("今天/半小时内".equals(orderPickStr)){
            return now.plusMinutes(30);
        }
        if("今天/立即取件".equals(orderPickStr)){
            return now.plusMinutes(30);
        }
        LocalDate date=LocalDate.now();
        if (orderPickStr.contains("明天")){
            date=date.plusDays(1);
        }
        else if(orderPickStr.contains("后天")){
            date=date.plusDays(2);
        }
        if (orderPickStr.length()<14){
            String[] nums= StringUtils.strGetNum(orderPickStr).split(";");
            for (int i = 0; i < nums.length; i++) {
                if (nums[i].length()<2){
                    nums[i]=0+nums[i];
                }
            }
            return LocalDateTime.of(date, LocalTime.parse(nums[2]+":"+nums[3]+":00"));
        }
        return LocalDateTime.of(date,LocalTime.parse(orderPickStr.substring(9,14)+":00"));

    }

    /**
     * 判断是否为预约单
     * @param type
     * @return
     */
    public static Boolean contrast(String pickTime){
        String[] strArr = {"今天/2小时内","今天/一小时内","今天/半小时内","今天/立即取件"};
        boolean res = Arrays.asList(strArr).contains(pickTime);
        return res;
    }

}
