package com.ruoyi.oa.utils;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.oa.domain.OaExpress;
import com.ruoyi.oa.domain.vo.OaExpressVo;
import sun.misc.BASE64Encoder;
import com.ruoyi.common.utils.DateUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.net.URLEncoder;
import java.util.UUID;
import java.util.List;
import java.util.Arrays;
import java.util.Date;

/**
 * 顺丰路由地址查询工具
 */
public class SfRouteQueryUtil {
    // 顺丰开放平台 partnerID
    private static final String PARTNER_ID = "YIX65G10";
    // 顺丰开放平台接口地址
    private static final String API_URL = "https://bspgw.sf-express.com/std/service";

    // 顺丰开放平台 checkWord
    private static final String CHECK_WORD = "PkJL4cpEQIUuV1goWvhIznqthletmddX";

    // 顺丰OAuth认证
    private static final String OAUTH_URL = "https://sfapi.sf-express.com/oauth2/accessToken";

    private static final String GRANT_TYPE = "password";
    /**
     * 查询顺丰路由
     * @param mailNo 顺丰运单号
     * @return 查询结果JSON
     */
    public static String queryRoute(String mailNo,String phoneNumber) {
        List<String> mailNos = Arrays.asList(mailNo);
        try {
            // 1. 构造业务数据msgData
            JSONObject msgData = new JSONObject();
            msgData.put("language", "zh-CN");
            msgData.put("trackingType", "1"); // 1:运单号 2:订单号
            msgData.put("methodType", "1");   // 1:标准路由
            msgData.put("trackingNumber", mailNos);
            msgData.put("checkPhoneNo", StringUtils.right(phoneNumber, 4));
            String msgDataStr = msgData.toJSONString();
            System.out.println(msgDataStr);

            // 2. 公共参数
            String requestID = UUID.randomUUID().toString().replaceAll("-", "");
            String serviceCode = "EXP_RECE_SEARCH_ROUTES";
            String timestamp = String.valueOf(System.currentTimeMillis());
//            String msgDigest = genSign(msgDataStr, timestamp, CHECK_WORD);
//            System.out.println(msgDigest);
            String accessToken = oAuth();
            System.out.println(accessToken);
            // 3. 拼接表单参数
            StringBuilder formParams = new StringBuilder();
            formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8"));
            formParams.append("&requestID=").append(URLEncoder.encode(requestID, "UTF-8"));
            formParams.append("&serviceCode=").append(URLEncoder.encode(serviceCode, "UTF-8"));
            formParams.append("&timestamp=").append(URLEncoder.encode(timestamp, "UTF-8"));
            formParams.append("&accessToken=").append(URLEncoder.encode(accessToken, "UTF-8"));
            formParams.append("&msgData=").append(URLEncoder.encode(msgDataStr, "UTF-8"));
            String formBody = formParams.toString();
            System.out.println(formBody);

            // 4. 发送POST请求
            return doPost(API_URL, formBody);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }



    /**
     * 顺丰msgDigest生成方式：Base64(MD5(URLEncode(msgData+timestamp+partnerId+checkWord)))
     */
    private static String genSign(String msgData, String timestamp, String checkWord) throws Exception {
        String toVerifyText = msgData + timestamp + checkWord;
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        md5.update(toVerifyText.getBytes("UTF-8"));
        byte[] digest = md5.digest();
        return Base64.getEncoder().encodeToString(digest);
    }

    /**
     * 顺丰OAUTH2
     */
    private static String oAuth() throws Exception {
        StringBuilder formParams = new StringBuilder();
        formParams.append("partnerID=").append(URLEncoder.encode(PARTNER_ID, "UTF-8"));
        formParams.append("&secret=").append(URLEncoder.encode(CHECK_WORD, "UTF-8"));
        formParams.append("&grantType=").append(URLEncoder.encode(GRANT_TYPE, "UTF-8"));
        String oauthResponse = doPost(OAUTH_URL, formParams.toString());
        JSONObject jsonObject = JSON.parseObject(oauthResponse);
        return jsonObject.getString("accessToken");
    }
    /**
     * 发送POST请求（表单格式）
     */
    private static String doPost(String urlStr, String formBody) throws Exception {
        URL url = new URL(urlStr);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
        conn.setDoOutput(true);
        try (OutputStream os = conn.getOutputStream()) {
            os.write(formBody.getBytes(StandardCharsets.UTF_8));
        }
        int code = conn.getResponseCode();
        if (code == 200) {
            try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }
                return sb.toString();
            }
        } else {
            throw new RuntimeException("HTTP请求失败，状态码：" + code);
        }
    }

    public static OaExpressVo parseData(String result) {
        if (StringUtils.isBlank(result)) {
            return null;
        }

        try {
            // 1. 解析最外层的JSON
            JSONObject outerJson = JSON.parseObject(result);
            if (outerJson == null) {
                return null;
            }

            // 2. 获取apiResultData字符串并再次解析
            String apiResultDataStr = outerJson.getString("apiResultData");
            if (StringUtils.isBlank(apiResultDataStr)) {
                return null;
            }

            JSONObject innerJson = JSON.parseObject(apiResultDataStr);
            if (innerJson == null) {
                return null;
            }

            // 3. 提取所需数据
            JSONObject msgData = innerJson.getJSONObject("msgData");
            if (msgData == null) {
                return null;
            }

            JSONArray routeResps = msgData.getJSONArray("routeResps");
            if (routeResps == null || routeResps.isEmpty()) {
                return null;
            }

            JSONObject firstRouteResp = routeResps.getJSONObject(0);
            if (firstRouteResp == null) {
                return null;
            }

            JSONArray routes = firstRouteResp.getJSONArray("routes");
            if (routes == null || routes.isEmpty()) {
                return null;
            }

            JSONObject lastRoute = routes.getJSONObject(routes.size() - 1);
            if (lastRoute == null) {
                return null;
            }

            String acceptTime = lastRoute.getString("acceptTime");
            String firstStatusName = lastRoute.getString("firstStatusName");

            OaExpressVo oaExpressVo = new OaExpressVo();
            // 转换日期并设置，如果日期格式不正确则设置为null
            if (StringUtils.isNotBlank(acceptTime)) {
                try {
                    Date date = DateUtils.parseDate(acceptTime);
                    oaExpressVo.setAcceptTime(date);
                } catch (Exception e) {
                    oaExpressVo.setAcceptTime(null);
                }
            }
            oaExpressVo.setFirstStatusName(firstStatusName);
            System.out.println(acceptTime);
            System.out.println(firstStatusName);
            return oaExpressVo;

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * main方法测试
     */
    public static void main(String[] args) {


        String mailNo = "SF3191365477469";
        String result = queryRoute(mailNo,"15075462410");
        System.out.println(result);
        OaExpressVo oaExpress = parseData(result);
    }
} 