package com.njzscloud.supervisory.gps.jike;

import com.njzscloud.supervisory.config.JikeProperties;
import com.njzscloud.supervisory.gps.jike.support.JikeSignUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.TreeMap;

/**
 * 即刻物联HTTP客户端
 */
@Slf4j
public class JikeApiClient {

    private final JikeProperties properties;

    public JikeApiClient(JikeProperties properties) {
        this.properties = properties;
    }

    /**
     * GET请求
     * @param uri 接口路径，如 /open-api/gps-trace/list
     * @param queryString 参数字符串，如 carNum=京A12345&stime=1746777600000&etime=1746864000000
     */
    public String doGet(String uri, String queryString) throws Exception {
        String endpoint = properties.getEndpoint();
        String url = endpoint + uri;

        long timestamp = System.currentTimeMillis();
        String appId = properties.getAppId();
        String secret = properties.getSecretKey();

        // 计算参数签名 - 使用原始值（不编码）
        String paramMd5 = JikeSignUtil.buildParamSignature(queryString);
        // 计算最终签名 - GET请求不包含body-signature
        String finalSign = JikeSignUtil.buildGetFinalSignature(appId, paramMd5, secret, timestamp);

        log.info("Jike GET request queryString: {}", queryString);
        log.info("Jike param-signature: {}", paramMd5);
        log.info("Jike final-signature: {}", finalSign);

        // 构建URL，参数值需要URL编码
        String finalUrl = url;
        if (queryString != null && !queryString.isEmpty()) {
            StringBuilder encodedUrl = new StringBuilder(url).append("?");
            String[] pairs = queryString.split("&");
            for (int i = 0; i < pairs.length; i++) {
                if (i > 0) {
                    encodedUrl.append("&");
                }
                String pair = pairs[i];
                int eqIdx = pair.indexOf("=");
                if (eqIdx > 0) {
                    String key = pair.substring(0, eqIdx);
                    String value = pair.substring(eqIdx + 1);
                    encodedUrl.append(key).append("=").append(URLEncoder.encode(value, "UTF-8"));
                } else {
                    encodedUrl.append(pair);
                }
            }
            finalUrl = encodedUrl.toString();
        }

        log.info("Jike GET final url: {}", finalUrl);

        HttpURLConnection conn = (HttpURLConnection) new URL(finalUrl).openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(10000);
        conn.setReadTimeout(30000);
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("x-jk-appid", appId);
        conn.setRequestProperty("x-jk-timestamp", String.valueOf(timestamp));
        conn.setRequestProperty("x-jk-param-signature", paramMd5);
        conn.setRequestProperty("x-jk-signature", finalSign);

        return readResponse(conn);
    }

    /**
     * GET请求 - 使用Map参数
     */
    public String doGet(String uri, Map<String, String> params) throws Exception {
        if (params == null || params.isEmpty()) {
            return doGet(uri, (String) null);
        }
        // 先排序，再构建字符串
        TreeMap<String, String> sorted = new TreeMap<>();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                continue;
            }
            sorted.put(entry.getKey(), entry.getValue());
        }
        
        String endpoint = properties.getEndpoint();
        String url = endpoint + uri;

        long timestamp = System.currentTimeMillis();
        String appId = properties.getAppId();
        String secret = properties.getSecretKey();

        // 构建URL（参数值需要URL编码）
        StringBuilder urlSb = new StringBuilder(url).append("?");
        boolean first = true;
        for (Map.Entry<String, String> entry : sorted.entrySet()) {
            if (!first) {
                urlSb.append("&");
            }
            urlSb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            first = false;
        }
        String finalUrl = urlSb.toString();

        // 计算参数签名 - 使用原始值（不编码），按文档说明
        StringBuilder signSb = new StringBuilder();
        first = true;
        for (Map.Entry<String, String> entry : sorted.entrySet()) {
            if (!first) {
                signSb.append("&");
            }
            signSb.append(entry.getKey()).append("=").append(entry.getValue());
            first = false;
        }
        String signQueryString = signSb.toString();

        String paramMd5 = JikeSignUtil.buildParamSignature(signQueryString);
        // 计算最终签名 - GET请求不包含body-signature
        String finalSign = JikeSignUtil.buildGetFinalSignature(appId, paramMd5, secret, timestamp);

        log.info("Jike GET request queryString (for sign): {}", signQueryString);
        log.info("Jike GET final url: {}", finalUrl);
        log.info("Jike param-signature: {}", paramMd5);
        log.info("Jike final-signature: {}", finalSign);

        HttpURLConnection conn = (HttpURLConnection) new URL(finalUrl).openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(10000);
        conn.setReadTimeout(30000);
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("x-jk-appid", appId);
        conn.setRequestProperty("x-jk-timestamp", String.valueOf(timestamp));
        conn.setRequestProperty("x-jk-param-signature", paramMd5);
        conn.setRequestProperty("x-jk-signature", finalSign);

        return readResponse(conn);
    }

    /**
     * POST请求
     */
    public String doPost(String uri, Map<String, String> params, String jsonBody) throws Exception {
        String endpoint = properties.getEndpoint();
        String url = endpoint + uri;

        log.info("Jike POST request: {}, body: {}", url, jsonBody);

        long timestamp = System.currentTimeMillis();
        String appId = properties.getAppId();
        String secret = properties.getSecretKey();

        // 计算body签名
        String bodyMd5 = JikeSignUtil.md5Hex(jsonBody);
        // 计算参数签名(POST时body参与签名)
        String paramMd5 = JikeSignUtil.buildPostParamSignature(params, bodyMd5);
        // 计算最终签名
        String finalSign = JikeSignUtil.buildFinalSignature(appId, bodyMd5, paramMd5, secret, timestamp);

        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setConnectTimeout(10000);
        conn.setReadTimeout(30000);
        conn.setRequestProperty("Accept", "application/json");
        conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
        conn.setRequestProperty("x-jk-appid", appId);
        conn.setRequestProperty("x-jk-timestamp", String.valueOf(timestamp));
        conn.setRequestProperty("x-jk-param-signature", paramMd5);
        conn.setRequestProperty("x-jk-body-signature", bodyMd5);
        conn.setRequestProperty("x-jk-signature", finalSign);

        if (jsonBody != null && !jsonBody.isEmpty()) {
            try (OutputStream os = conn.getOutputStream()) {
                os.write(jsonBody.getBytes(StandardCharsets.UTF_8));
            }
        }

        return readResponse(conn);
    }

    private String buildUrl(String baseUrl, Map<String, String> params) throws Exception {
        if (params == null || params.isEmpty()) {
            return baseUrl;
        }
        StringBuilder sb = new StringBuilder(baseUrl).append("?");
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (entry.getValue() == null || entry.getValue().isEmpty()) {
                continue;
            }
            if (!first) {
                sb.append("&");
            }
            sb.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            first = false;
        }
        return sb.toString();
    }

    private String readResponse(HttpURLConnection conn) throws Exception {
        int code = conn.getResponseCode();
        InputStream is = (code >= 200 && code < 400) ? conn.getInputStream() : conn.getErrorStream();
        StringBuilder sb = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
        }
        return sb.toString();
    }
}
