package org.dromara.daping.utils;

import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import org.dromara.daping.domain.GinlongApiEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class GinlongApiClient {

    private static final String CONTENT_TYPE = "application/json";

    // 直接注入从配置文件绑定的实体类
    @Autowired
    private GinlongApiEntity apiEntity;

    /**
     * 通用API调用方法
     *
     * @param path      接口路径（如：/v1/api/userStationList）
     * @param params    请求参数（无参数时传null）
     * @param apiEntity
     * @return 接口返回的JSON字符串
     * @throws Exception 可能的异常（签名失败、网络错误等）
     */
    public String callApi(String path, Map<String, Object> params, GinlongApiEntity apiEntity) throws Exception {
        // 1. 处理请求体（转为JSON字符串）
        String body = (params != null) ? JSONUtil.toJsonStr(params) : "{}";
        // 2. 计算Content-MD5
        String contentMd5 = calcContentMD5(body);
        // 3. 获取GMT时间（需在当前时间±15分钟内）
        String gmtDate = getGMTDate();
        // 4. 计算签名
        String signature = buildSignature(path, contentMd5, gmtDate,apiEntity);
        // 5. 构建完整请求URL
        String url = apiEntity.getUrl() + path;

        // 6. 发送POST请求并返回结果
        HttpResponse response = HttpRequest.post(url)
            .header("Content-Type", CONTENT_TYPE)
            .header("Content-MD5", contentMd5)
            .header("Date", gmtDate)
            .header("Authorization", "API " + apiEntity.getKey() + ":" + signature)  // 使用实体类的key
            .body(body)
            .execute();

        return response.body();
    }


    /**
     * 计算Content-MD5（按文档规范）
     */
    private String calcContentMD5(String body) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(body.getBytes(StandardCharsets.UTF_8));
            byte[] digest = md.digest();
            return Base64.getEncoder().encodeToString(digest);
        } catch (Exception e) {
            throw new RuntimeException("计算Content-MD5失败", e);
        }
    }

    /**
     * 获取符合格式的GMT时间
     */
    private String getGMTDate() {
        //1、获取GMT时区下的当前时间；
        Calendar calendar = Calendar.getInstance();
        //2、将当前时间按以下格式转换为字符串。 格式：EEE, d MMM yyyy HH:mm:ss 'GMT'注意：Date 时间不能超出当前时间的正负15分钟，否则会出现调用失败。
        SimpleDateFormat sdf = new SimpleDateFormat(
            "EEE, d MMM yyyy HH:mm:ss 'GMT'",
            Locale.US
        );
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        return sdf.format(calendar.getTime());
    }


    /**
     * 构建签名（按文档规范）
     */
    private String buildSignature(String path, String contentMd5, String gmtDate, GinlongApiEntity apiEntity) {
        // 拼接签名原文
        String signatureText = "POST" + "\n"
            + contentMd5 + "\n"
            + CONTENT_TYPE + "\n"
            + gmtDate + "\n"
            + path;
        // 计算HmacSHA1并Base64编码
        HMac hmac = new HMac(
            HmacAlgorithm.HmacSHA1,
            apiEntity.getSecret().getBytes(StandardCharsets.UTF_8));  // 使用实体类的secret
        return hmac.digestBase64(signatureText, false);
    }
}
