package com.sikey.wa04.common.utils;

import cn.hutool.json.JSONUtil;
import lombok.extern.log4j.Log4j2;
import okhttp3.*;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Log4j2
public class BaiduLocationApiClient {
    private final OkHttpClient client = new OkHttpClient();
    private final String apiUrl = "https://api.map.baidu.com/locapi/v2";
    private final String key = "suBnrGHXb5K7iPUtipyLPDBzPHlnSMqc";

    public String locate(Map<String, Object> params) throws Exception{
        // 构建请求体（JSON）
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("key", key);
        map.put("src", "sikey");
        map.put("prod", "ha04");
        map.put("ver", "1.0");
        map.put("trace", false);


        // 准备发送请求的参数
        Map<String, Object> requestParams = new LinkedHashMap<>(params); // 保持插入顺序

        List<Object> list = new ArrayList<>();
        list.add(requestParams);
        Map<String, Object> map2 = new LinkedHashMap<>(map);
        map2.put("body", list);

        // 使用 TreeMap 按 key 字母顺序排序
        TreeMap<String, Object> sortedParams = new TreeMap<>(map2);

        // 计算 SN
        String paramsStr = toQueryString(sortedParams);
        String wholeStr = "/locapi/v2?" + paramsStr;
        String tempStr = URLEncoder.encode(wholeStr, "UTF-8");
        String sn = MD5(tempStr);

        map.put("body", list);

        // 构建请求头
        Headers headers = new Headers.Builder()
                .add("key", String.valueOf(map.get("key")))
                .add("src", String.valueOf(map.get("src")))
                .add("prod", String.valueOf(map.get("prod")))
                .add("ver", String.valueOf(map.get("ver")))
                .add("trace", Boolean.toString(false))
                .add("sn", sn)
                .build();
        // 构建请求
        RequestBody body = RequestBody.create(JSONUtil.toJsonStr(map), MediaType.parse("application/json"));
        Request request = new Request.Builder().url(apiUrl).headers(headers).post(body).build();

        log.info("[请求百度地图]参数：{}", JSONUtil.toJsonStr(map));

        // 执行请求并返回响应
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            return response.body().string();
        }
    }

    // 将 Map 转换为查询字符串
    private String toQueryString(Map<String, Object> data) throws UnsupportedEncodingException {
        StringBuffer queryString = new StringBuffer();
        for (Map.Entry<?, ?> pair : data.entrySet()) {
            queryString.append(pair.getKey() + "=");
            queryString.append(URLEncoder.encode(String.valueOf(pair.getValue()) ,
                    "UTF-8") + "&");
        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();
        /*StringBuilder queryString = new StringBuilder();
        for (Map.Entry<String, Object> pair : data.entrySet()) {
            if (Objects.isNull(pair.getValue())) {
                continue;
            }
            queryString.append(pair.getKey()).append("=");
            if (pair.getValue() instanceof Boolean) {
                queryString.append(URLEncoder.encode(Boolean.toString((Boolean) pair.getValue()), "UTF-8")).append("&");
            } else if (pair.getValue() instanceof String) {
                queryString.append(URLEncoder.encode(String.valueOf(pair.getValue()), "UTF-8")).append("&");
            }

        }
        if (queryString.length() > 0) {
            queryString.deleteCharAt(queryString.length() - 1);
        }
        return queryString.toString();*/
    }

    // MD5 计算方法
    // 来自stackoverflow的MD5计算方法，调用了MessageDigest库函数，并把byte数组结果转换成16进制
    public String MD5(String md5) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(md5.getBytes());
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < array.length; ++i) {
                sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
        }
        return null;
    }
}
