package com.gxwebsoft.common.core.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.spec.AlgorithmParameterSpec;

/**
 * 微信小程序数据解密工具类
 * 用于解密微信小程序的encryptedData数据
 * 
 * @author WebSoft
 */
public class WxMiniProgramDecryptUtil {

    /**
     * 解密微信小程序数据
     * 
     * @param encryptedData 加密的数据
     * @param sessionKey 会话密钥
     * @param iv 初始向量
     * @return 解密后的JSON字符串
     * @throws Exception 解密失败时抛出异常
     */
    public static String decrypt(String encryptedData, String sessionKey, String iv) throws Exception {
        // Base64解码
        byte[] dataByte = Base64.decodeBase64(encryptedData);
        byte[] keyByte = Base64.decodeBase64(sessionKey);
        byte[] ivByte = Base64.decodeBase64(iv);

        try {
            // 如果密钥长度不够，则补齐到32位
            if (keyByte.length % 16 != 0) {
                int groups = keyByte.length / 16 + (keyByte.length % 16 != 0 ? 1 : 0);
                byte[] temp = new byte[groups * 16];
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }

            // 初始化
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameterSpec paramSpec = new IvParameterSpec(ivByte);
            cipher.init(Cipher.DECRYPT_MODE, spec, paramSpec);

            // 解密
            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, StandardCharsets.UTF_8);
                return result;
            }
        } catch (Exception e) {
            throw new Exception("微信小程序数据解密失败", e);
        }
        return null;
    }

    /**
     * 解密手机号信息
     * 
     * @param encryptedData 加密的数据
     * @param sessionKey 会话密钥
     * @param iv 初始向量
     * @return 手机号码，解密失败返回null
     */
    public static String decryptPhoneNumber(String encryptedData, String sessionKey, String iv) {
        try {
            String decryptedData = decrypt(encryptedData, sessionKey, iv);
            if (decryptedData != null) {
                JSONObject jsonObject = JSON.parseObject(decryptedData);
                return jsonObject.getString("phoneNumber");
            }
        } catch (Exception e) {
            System.err.println("解密手机号失败: " + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 解密用户信息
     * 
     * @param encryptedData 加密的数据
     * @param sessionKey 会话密钥
     * @param iv 初始向量
     * @return 解密后的用户信息JSON对象，解密失败返回null
     */
    public static JSONObject decryptUserInfo(String encryptedData, String sessionKey, String iv) {
        try {
            String decryptedData = decrypt(encryptedData, sessionKey, iv);
            if (decryptedData != null) {
                return JSON.parseObject(decryptedData);
            }
        } catch (Exception e) {
            System.err.println("解密用户信息失败: " + e.getMessage());
            e.printStackTrace();
        }
        return null;
    }
}
