package com.kingdee.eas.custom.integration.base.util;

import javax.crypto.Cipher;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * AppSecret 解密工具（纯 JDK，无框架依赖）
 * <p>
 * YAML 中 appSecret 存储格式：ENC(Base64密文)
 * 算法：AES-256-GCM
 * 密钥：通过环境变量 OAUTH_ENCRYPT_KEY 传入，32字节
 * <p>
 * 密文生成（运维侧执行一次，可用配套工具类生成）：
 * iv(12字节随机) + AES-GCM加密结果 → Base64 → ENC(...)
 */
public class AppSecretDecryptor {

    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int IV_LENGTH = 12;
    private static final int TAG_LENGTH = 128;
    private static final String ENC_PREFIX = "ENC(";
    private static final String ENC_SUFFIX = ")";

    private final String encryptKey;

    public AppSecretDecryptor(String encryptKey) {
        if (encryptKey == null || encryptKey.trim().isEmpty()) {
            throw new IllegalArgumentException(
                    "OAUTH_ENCRYPT_KEY 未配置，无法启动");
        }
        this.encryptKey = encryptKey;
    }

    /**
     * 加密明文，返回 ENC(Base64密文) 格式，供运维写入配置文件。
     */
    public String encrypt(String plaintext) {
        try {
            byte[] iv = new byte[IV_LENGTH];
            new SecureRandom().nextBytes(iv);

            SecretKeySpec keySpec = new SecretKeySpec(
                    encryptKey.getBytes("UTF-8"), "AES");
            GCMParameterSpec gcmSpec = new GCMParameterSpec(TAG_LENGTH, iv);

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmSpec);
            byte[] enc = cipher.doFinal(plaintext.getBytes("UTF-8"));

            byte[] raw = new byte[IV_LENGTH + enc.length];
            System.arraycopy(iv, 0, raw, 0, IV_LENGTH);
            System.arraycopy(enc, 0, raw, IV_LENGTH, enc.length);

            return ENC_PREFIX + Base64.getEncoder().encodeToString(raw) + ENC_SUFFIX;

        } catch (Exception e) {
            throw new IllegalStateException("AppSecret 加密失败", e);
        }
    }

    /**
     * 解密 appSecret。
     * 若值不是 ENC(...) 格式，视为明文直接返回（兼容开发环境）。
     */
    public String decrypt(String value) {
        if (value == null || !value.startsWith(ENC_PREFIX)) {
            return value;
        }
        String base64 = value.substring(
                ENC_PREFIX.length(), value.length() - ENC_SUFFIX.length());
        try {
            byte[] raw = Base64.getDecoder().decode(base64);
            byte[] iv = new byte[IV_LENGTH];
            byte[] enc = new byte[raw.length - IV_LENGTH];
            System.arraycopy(raw, 0, iv, 0, IV_LENGTH);
            System.arraycopy(raw, IV_LENGTH, enc, 0, enc.length);

            SecretKeySpec keySpec = new SecretKeySpec(
                    encryptKey.getBytes("UTF-8"), "AES");
            GCMParameterSpec gcmSpec = new GCMParameterSpec(TAG_LENGTH, iv);

            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmSpec);
            return new String(cipher.doFinal(enc), "UTF-8");

        } catch (Exception e) {
            throw new IllegalStateException(
                    "AppSecret 解密失败，请检查加密密钥和密文格式", e);
        }
    }

    // -------------------------------------------------------------------------
    // 命令行加密工具
    // -------------------------------------------------------------------------

    /**
     * 生成AES-256密钥。
     * 输出32字节随机密钥的Base64编码字符串，可直接设为OAUTH_ENCRYPT_KEY。
     */
    public static String generateKey() {
        byte[] key = new byte[32];
        new SecureRandom().nextBytes(key);
        return Base64.getEncoder().encodeToString(key);
    }

    /**
     * 运维侧加密工具，上线前执行一次生成密文。
     * <p>
     * 用法：
     * set OAUTH_ENCRYPT_KEY=你的32字节密钥
     * java com.kingdee.eas.custom.integration.hr.auth.config.AppSecretDecryptor 明文AppSecret
     * <p>
     * 输出：ENC(Base64密文)，直接写入 oauth-config.json 的 appSecret 字段。
     */
    public static void main(String[] args) {
//        String key = "DLxPesllj66BRL8rpp0DoFgTr5qYMv0i";
//        if (key == null || key.trim().isEmpty()) {
//            System.err.println("错误: 环境变量 OAUTH_ENCRYPT_KEY 未设置");
//            System.exit(1);
//        }
//
//        AppSecretDecryptor tool = new AppSecretDecryptor(key);
//        System.out.println(tool.encrypt("zpHfRgQd9wkWzfhvmjknIC8htiywloA5"));


        System.out.println(generateKey());

    }
}
