package com.heyu.api.data.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Base64;

/**
 * 微信回调验证和加解密工具类
 */
public class WeChatCallbackUtil {
    
    /**
     * 验证回调 URL
     * 
     * @param token Token
     * @param timestamp 时间戳
     * @param nonce 随机字符串
     * @param msgSignature 消息签名
     * @param echostr 加密的随机字符串
     * @param encodingAESKey EncodingAESKey
     * @return 解密后的 echostr
     * @throws Exception 验证失败或解密失败
     */
    public static String verifyURL(String token, String timestamp, 
                                   String nonce, String msgSignature, 
                                   String echostr, String encodingAESKey) throws Exception {
        // 1. 验证签名
        String signature = generateSignature(token, timestamp, nonce, echostr);
        if (!signature.equals(msgSignature)) {
            throw new Exception("签名验证失败");
        }
        
        // 2. 解密 echostr
        String result = decrypt(echostr, encodingAESKey);
        return result;
    }
    
    /**
     * 生成签名
     */
    public static String generateSignature(String token, String timestamp,
                                           String nonce, String echostr) throws Exception {
        // 将 token、timestamp、nonce、echostr 按字典序排序
        String[] arr = {token, timestamp, nonce, echostr};
        Arrays.sort(arr);
        
        // 拼接字符串
        StringBuilder sb = new StringBuilder();
        for (String s : arr) {
            sb.append(s);
        }
        
        // SHA1 加密
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] digest = md.digest(sb.toString().getBytes(StandardCharsets.UTF_8));
        
        // 转换为十六进制字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : digest) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        
        return hexString.toString();
    }
    
    /**
     * AES 解密
     */
    public static String decrypt(String encryptedData, String encodingAESKey) throws Exception {
        // Base64 解码
        byte[] keyBytes = Base64.getDecoder().decode(encodingAESKey);
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
        
        // 提取前 16 字节作为 IV
        byte[] iv = new byte[16];
        System.arraycopy(encryptedBytes, 0, iv, 0, 16);
        
        // 提取加密内容
        byte[] ciphertext = new byte[encryptedBytes.length - 16];
        System.arraycopy(encryptedBytes, 16, ciphertext, 0, ciphertext.length);
        
        // AES-256-CBC 解密
        SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
        IvParameterSpec ivSpec = new IvParameterSpec(iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
        
        byte[] decrypted = cipher.doFinal(ciphertext);
        
        // 去除填充并提取消息内容
        // 前 4 字节是消息长度，最后是随机字符串
        int contentLength = bytesToInt(decrypted, 0);
        byte[] content = new byte[contentLength];
        System.arraycopy(decrypted, 4, content, 0, contentLength);
        
        return new String(content, StandardCharsets.UTF_8);
    }
    
    /**
     * 字节数组转整数（大端序）
     */
    private static int bytesToInt(byte[] bytes, int offset) {
        return ((bytes[offset] & 0xFF) << 24) |
               ((bytes[offset + 1] & 0xFF) << 16) |
               ((bytes[offset + 2] & 0xFF) << 8) |
               (bytes[offset + 3] & 0xFF);
    }
}