package com.ruoyi.aicall.utils;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
public final class SignClientUtils {

    private static final int CONN_TIMEOUT = 5_000;   // 连接超时
    private static final int READ_TIMEOUT = 30_000;  // 读取超时
    private static final String UTF8 = StandardCharsets.UTF_8.name();

    /** 统一签名入口 */
    public static String sign(String appSecret,
                              String method,
                              String urlWithQuery,
                              Map<String, String> headers,
                              String body) throws Exception {
        // 1. 提取 query 参数
        Map<String, String> all = new TreeMap<>();
        int q = urlWithQuery.indexOf('?');
        if (q > 0) {
            String query = urlWithQuery.substring(q + 1);
            Arrays.stream(query.split("&"))
                    .filter(s -> !s.isEmpty())
                    .forEach(p -> {
                        String[] kv = p.split("=", 2);
                        all.put(kv[0], kv.length == 2 ? kv[1] : "");
                    });
        }

        // 2. 加入 body
        if ("POST".equalsIgnoreCase(method) && body != null) {
            String ct = headers.getOrDefault("Content-Type", "");
            if (ct.contains("x-www-form-urlencoded")) {
                Arrays.stream(body.split("&"))
                        .forEach(p -> {
                            String[] kv = p.split("=", 2);
                            all.put(kv[0], kv.length == 2 ? kv[1] : "");
                        });
            } else if (ct.contains("json")) {
                all.put("_body", body);   // 直接整段 json
            }
        }

        // 3. 拼接待签名字符串
        String base = all.entrySet().stream()
                .map(e -> e.getKey() + "=" + e.getValue())
                .collect(Collectors.joining("&"));

        // 4. HMAC-SHA256
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appSecret.getBytes(UTF8), "HmacSHA256"));
        byte[] hash = mac.doFinal(base.getBytes(UTF8));
        return bytesToHex(hash);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes) sb.append(String.format("%02x", b));
        return sb.toString();
    }

    private static Map<String, String> mapOf(Object... kv) {
        Map<String, String> m = new HashMap<>();
        for (int i = 0; i < kv.length; i += 2) {
            m.put(kv[i].toString(), kv[i + 1].toString());
        }
        return m;
    }


    /* ================== GET ================== */
    public static String get(String url,
                             Map<String, String> headers) throws IOException {
        return get(url, null, headers);
    }

    public static String get(String url,
                             String query,
                             Map<String, String> headers) throws IOException {

        String fullUrl = query == null || query.isEmpty() ? url : url + "?" + query;
        HttpURLConnection conn = (HttpURLConnection) new URL(fullUrl).openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(CONN_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);
        setHeaders(conn, headers);
        return readResponse(conn);
    }

    /* ================== POST ================== */
    public static String post(String url,
                              Map<String, String> headers,
                              String body) throws IOException {

        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);           // 允许写 body
        conn.setConnectTimeout(CONN_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);

        setHeaders(conn, headers);

        // 写 body
        if (body != null) {
            try (OutputStream os = conn.getOutputStream()) {
                os.write(body.getBytes(StandardCharsets.UTF_8));
            }
        }

        return readResponse(conn);
    }

    /* ================== 内部工具 ================== */
    private static void setHeaders(HttpURLConnection conn, Map<String, String> headers) {
        if (headers == null) return;
        headers.forEach(conn::setRequestProperty);
    }

    private static String readResponse(HttpURLConnection conn) throws IOException {
        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();
        }
    }






    /* =================== DEMO =================== */
    public static void main(String[] args) throws Exception {
        String appKey  = "AK_123456";
        String secret  = "1Tlam8MbCOdCYP6eviUtqIUtmGRl+Nm69NhxiMaFC64=";
        long ts        = System.currentTimeMillis();
        String nonce   = UUID.randomUUID().toString();

//        /* ---------- 示例1：GET ---------- */
//        String getUrl = "http://localhost:8899/aicall/api/gateway/list";
//        Map<String, String> getHeaders = mapOf(
//                "X-AppKey",    appKey,
//                "X-Timestamp", String.valueOf(ts),
//                "X-Nonce",     nonce,
//                "Content-Type", "application/x-www-form-urlencoded"
//        );
//        String getSign = sign(secret, "GET", getUrl, getHeaders, null);
//        log.info("GET  Sign = " + getSign);
//        getHeaders.put("X-Sign", getSign);
//        String response1 = get(getUrl, null, getHeaders);
//        log.info(response1);

        /* ---------- 示例2：POST JSON ---------- */
        JSONObject jsonBody = new JSONObject();
        jsonBody.put("taskId", 1);
        List<String> phoneList = new ArrayList<>();
        phoneList.add("1234567");
        jsonBody.put("phoneList", phoneList);
        String body = JSONObject.toJSONString(jsonBody);
        Map<String, String> postHeaders = mapOf(
                "X-AppKey",    appKey,
                "X-Timestamp", String.valueOf(ts),
                "X-Nonce",     nonce,
                "Content-Type", "application/json"
        );
        String postUrl = "http://localhost:8899/aicall/api/ai/addCallList";
        String postSign = sign(secret, "POST", postUrl, postHeaders, body);
        postHeaders.put("X-Sign", postSign);
        System.out.println("JSON Sign = " + postSign);
        String response2 = post(postUrl, postHeaders, body);
        log.info(response2);
    }
}
