package com.ruoyi.common.utils.sign;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * HMAC-SHA256 加密工具类（Java 1.8 原生实现）
 * 功能：hex(hmac-sha256(signatureString, secret))
 */
public class HmacSha256Utils {

    public static String hmacSha256To16Hex(String data,String secret) throws Exception {
        Mac sha256Hmac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        sha256Hmac.init(secKey);
        byte[] hash = sha256Hmac.doFinal(data.getBytes(StandardCharsets.UTF_8));

        // 转16进制
        StringBuilder sb = new StringBuilder(hash.length * 2);
        for (byte b : hash) sb.append(String.format("%02x", b));
        return sb.toString();
    }

    /**
     * HMAC-SHA256 加密并转为 16 进制字符串（默认 UTF-8 编码，大写结果）
     *
     * @param signatureString 待加密的字符串（原始签名串）
     * @param secret          密钥（加密密钥）
     * @return 16 进制编码的 HMAC-SHA256 结果（大写）
     * @throws NoSuchAlgorithmException 算法不存在（理论上不会抛出，Java 1.8 自带 HmacSHA256）
     * @throws InvalidKeyException      密钥无效（如密钥为空或格式错误）
     */
    public static String hmacSha256ToHex(String signatureString, String secret)
            throws NoSuchAlgorithmException, InvalidKeyException {
        // 1. 初始化 HMAC-SHA256 算法的 Mac 实例
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");

        // 2. 将密钥字符串转为 SecretKeySpec（UTF-8 编码）
        SecretKeySpec secretKey = new SecretKeySpec(
                secret.getBytes(StandardCharsets.UTF_8),
                "HmacSHA256"
        );

        // 3. 初始化 Mac 并计算摘要（待加密字符串按 UTF-8 转字节数组）
        hmacSha256.init(secretKey);
        byte[] hmacBytes = hmacSha256.doFinal(signatureString.getBytes(StandardCharsets.UTF_8));

        // 4. 将 HMAC 字节数组转为 16 进制字符串（大写）
        return bytesToHex(hmacBytes);
    }

    /**
     * 字节数组转为 16 进制字符串（大写，确保每个字节对应两位十六进制数）
     *
     * @param bytes HMAC 加密后的字节数组
     * @return 大写 16 进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder hexBuilder = new StringBuilder();
        for (byte b : bytes) {
            // 字节转十六进制（& 0xFF 避免负数问题）
            String hex = Integer.toHexString(b & 0xFF);
            // 不足两位补 0（如字节 0x0A 需转为 "0A"，而非 "A"）
            if (hex.length() == 1) {
                hexBuilder.append('0');
            }
            hexBuilder.append(hex.toUpperCase()); // 转为大写（如需小写，改为 toLowerCase()）
        }
        return hexBuilder.toString();
    }

    // ------------------------------ 测试示例 ------------------------------
    public static void main(String[] args) {
        try {
            // 待加密的签名串
            String signatureString = "HelloWorld123";
            // 加密密钥
            String secret = "mySecretKey123456";

            // 执行加密
            String hexResult = hmacSha256ToHex(signatureString, secret);

            // 输出结果（示例结果：8F7E2B9D3C7A1F0E4D6B8A0C2E5F3A7D9B0C4E6F8A1B3C5D7E9F0A2B4C6D8E0F）
            System.out.println("HMAC-SHA256 Hex 结果：" + hexResult);
        } catch (NoSuchAlgorithmException | InvalidKeyException e) {
            // 处理异常（实际项目中建议更友好的异常处理）
            e.printStackTrace();
        }
    }
}