package com.fjhx.uitl.kd100;

import cn.hutool.core.date.DateUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.fjhx.config.KD100Config;
import com.fjhx.constants.RedisConstant;
import com.fjhx.constants.logistics.LogisticsConstant;
import com.google.gson.Gson;
import com.kuaidi100.sdk.api.QueryTrack;
import com.kuaidi100.sdk.api.Subscribe;
import com.kuaidi100.sdk.contant.ApiInfoConstant;
import com.kuaidi100.sdk.core.IBaseClient;
import com.kuaidi100.sdk.pojo.HttpResult;
import com.kuaidi100.sdk.request.*;
import com.kuaidi100.sdk.utils.SignUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.tool.api.ResultCode;
import org.springblade.core.tool.utils.Func;

import java.net.URLDecoder;
import java.util.Date;
import java.util.Objects;

@Log4j2
public class KD100Util {

    private final static BladeRedis bladeRedis = SpringUtil.getBean(BladeRedis.class);

    /**
     * 实时快递查询接口
     *
     * @param com 快递公司编码
     * @param num 快递单号
     * @return
     */
    public static JSONObject queryTrack(String com, String num) {
        HttpResult result;
        try {
            QueryTrackReq queryTrackReq = new QueryTrackReq();
            QueryTrackParam queryTrackParam = new QueryTrackParam();
            queryTrackParam.setCom(com);
            queryTrackParam.setNum(num);
            String param = new Gson().toJson(queryTrackParam);

            queryTrackReq.setParam(param);
            queryTrackReq.setCustomer(KD100Config.getCustomer());
            queryTrackReq.setSign(SignUtils.querySign(param, KD100Config.getKey(), KD100Config.getCustomer()));

            IBaseClient baseClient = new QueryTrack();
            result = baseClient.execute(queryTrackReq);
        } catch (Exception e) {
            log.error(e.toString());
            throw new ServiceException("请求第三方快递信息异常，请联系管理员！");
        }
        return parseQueryResult(result);
    }

    /**
     * 订阅接口
     *
     * @param com 快递公司编码
     * @param num 快递单号
     * @return
     */
    public static JSONObject subscribe(String com, String num, Date date) {
        HttpResult result;
        try {
            SubscribeParameters subscribeParameters = new SubscribeParameters();
            subscribeParameters.setCallbackurl(KD100Config.getCallbackurl());

            SubscribeParam subscribeParam = new SubscribeParam();
            subscribeParam.setParameters(subscribeParameters);
            subscribeParam.setCompany(com);
            subscribeParam.setNumber(num);
            subscribeParam.setKey(KD100Config.getKey());

            SubscribeReq subscribeReq = new SubscribeReq();
            subscribeReq.setSchema(ApiInfoConstant.SUBSCRIBE_SCHEMA);
            subscribeReq.setParam(new Gson().toJson(subscribeParam));

            IBaseClient subscribe = new Subscribe();
            result = subscribe.execute(subscribeReq);
        } catch (Exception e) {
            log.error(e.toString());
            throw new ServiceException("请求第三方快递订阅功能异常，请联系管理员！");
        }
        return parseSubscribeData(result, com, num, date);
    }

    /**
     * 解析数据：查询结果
     *
     * @param result 数据结果
     * @return
     */
    private static JSONObject parseQueryResult(HttpResult result) {
        if (Func.isNotEmpty(result) && result.getStatus() == ResultCode.SUCCESS.getCode()) {
            JSONObject body = JSONObject.parseObject(result.getBody());
            if (Func.isNotEmpty(body.get("message")) && StringUtils.equalsIgnoreCase(body.getString("message"), "ok")) {
                return body;
            } else {
                throw new ServiceException("操作失败，原因：物流信息【" + body.getString("message") + "】，请稍后重试，或者联系管理员！");
            }
        } else {
            throw new ServiceException("物流信息查询失败，请稍后重试，或者联系管理员！");
        }
    }

    /**
     * 解析数据：订阅结果
     *
     * @param result 数据结果
     * @return
     */
    private static JSONObject parseSubscribeData(HttpResult result, String com, String num, Date date) {
        if (Func.isNotEmpty(result) && result.getStatus() == ResultCode.SUCCESS.getCode()) {
            JSONObject body = JSONObject.parseObject(result.getBody());
            if (Func.isNotEmpty(body) && body.getBoolean("result")) {
                return body;
            } else {

                if (DateUtil.betweenDay(new Date(), date, false) < 3) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("com", com);
                    jsonObject.put("num", num);
                    jsonObject.put("date", date);
                    bladeRedis.set(RedisConstant.KD_100_SEND_SUBSCRIBE + com + ":" + num, jsonObject);
                }

                log.error("监听物流消息失败： com:{}, num:{}, messageL{}", com, num, body.toString());

                return body;

                // throw new ServiceException("操作失败，原因：物流信息【" + body.getString("message") + "】，请稍后重试，或者联系管理员！");
            }
        } else {
            throw new ServiceException("物流信息订阅失败，请稍后重试，或者联系管理员！");
        }
    }

    /**
     * 解析数据：推送结果
     *
     * @param data 物流信息
     * @return
     */
    public static JSONObject parsePushData(String data) {
        if (StringUtils.isNotBlank(data) && StringUtils.indexOf(data, "param=") != -1) {
            data = StringUtils.substringAfter(data, "param=");
            try {
                data = URLDecoder.decode(data, "UTF-8");
            } catch (Exception e) {
                throw new ServiceException("物流信息推送失败，参数解码异常！");
            }

            JSONObject object = JSONObject.parseObject(data);
            if (Func.isNotEmpty(object) && Func.isNotEmpty(object.getJSONObject("lastResult"))) {
                JSONObject body = object.getJSONObject("lastResult");
                if (Func.isNotEmpty(body.get("message")) && StringUtils.equalsIgnoreCase(body.getString("message"), "ok")) {
                    return body;
                } else {
                    throw new ServiceException("物流信息推送失败，原因：物流信息【" + body.getString("message") + "】！");
                }
            } else {
                throw new ServiceException("物流信息推送失败，参数解析异常！");
            }
        } else {
            throw new ServiceException("物流信息推送失败！");
        }
    }

    public static Integer getLogisticsStatus(String logisticsCompanyCode, String code) {
        Integer itemState = -1;

        // 查询快递100的物流信息
        try {
            JSONObject result = KD100Util.queryTrack(logisticsCompanyCode, code);
            itemState = result.getInteger("state");
        } catch (Exception e) {

        }

        Integer state = itemState;
        new Thread(() -> {
            if (!Objects.equals(state, LogisticsConstant.KD100Status.STATUS_3)) {
                // 如果不是已签收状态，则开启订阅（物流状态跟踪并推送）
                KD100Util.subscribe(logisticsCompanyCode, code, new Date());
            }
        }).start();
        return state;
    }

}
