package com.cool.store.utils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * @Author suzhuhong
 * @Date 2025/4/2 9:36
 * @Version 1.0
 */

public class HmacSigner {

    private static final String HMAC_ALGORITHM = "HmacSHA256";
    private static final DateTimeFormatter GMT_FORMATTER =
            DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH)
                    .withZone(ZoneId.of("GMT"));

    /**
     * 生成与Postman完全一致的签名头
     */
    public static Map<String, String> generateHeaders(
            String username,
            String secret,
            String requestBody) throws Exception {

        // 1. 生成RFC 1123格式时间戳
        String curDate = ZonedDateTime.now(ZoneId.of("GMT"))
                .format(GMT_FORMATTER);

        // 2. 计算请求体摘要
        String computedDigest = computeDigest(requestBody);

        // 3. 构建签名字符串
        String signingString = "x-date: " + curDate + "\n" + "digest: " + computedDigest;

        // 4. 计算HMAC签名
        String signature = hmacSha256(secret, signingString);

        // 5. 组装Authorization头
        String authorization = String.format(
                "hmac username=\"%s\", algorithm=\"hmac-sha256\", headers=\"x-date digest\", signature=\"%s\"",
                username,
                signature
        );

        // 6. 返回头信息Map
        Map<String, String> headers = new HashMap<>();
        headers.put("x-Date", curDate);
        headers.put("Digest", computedDigest);
        headers.put("Authorization", authorization);
        return headers;
    }

    private static String computeDigest(String data) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash = md.digest(data.getBytes(StandardCharsets.UTF_8));
        return "SHA-256=" + Base64.getEncoder().encodeToString(hash);
    }

    private static String hmacSha256(String secret, String data) throws Exception {
        if (StringUtil.isEmpty(secret)){
            return "";
        }
        Mac mac = Mac.getInstance(HMAC_ALGORITHM);
        mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_ALGORITHM));
        byte[] hash = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(hash);
    }
}