package org.dromara.zhishu.util;

import org.dromara.zhishu.domain.dto.SuccessDataItemDto;
import org.springframework.util.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;

/**
 * 商品导出数据解密工具类
 * 对应 Python 脚本的解密逻辑
 */
public class DecryptUtils {

    // 固定主密钥的 Base64 表示 (对应 Python 中的 MASTER_KEY_BASE64)
    private static final String MASTER_KEY_BASE64 = "sx3ad0ApTJnKTSByRWwJQG/gO8CiCYzLjHTTMza0Aw0=";

    // Nonce 长度：8字节
    private static final int NONCE_BYTES = 8;

    // 需要解密的字段名列表
    private static final String[] ENCRYPTED_FIELDS = {"isbn", "goodsCode", "title", "skuCode"};

    // 主密钥
    private static byte[] masterKey;

    static {
        try {
            masterKey = Base64.getDecoder().decode(MASTER_KEY_BASE64);
            if (masterKey.length != 32) {
                throw new RuntimeException("主密钥长度错误：期望 32 字节，实际 " + masterKey.length + " 字节");
            }
        } catch (Exception e) {
            throw new RuntimeException("初始化解密密钥失败", e);
        }
    }

    /**
     * 解密单个加密字段值（增加判断）
     */
    private static String decryptField(String encryptedValue) throws Exception {
        if (!StringUtils.hasText(encryptedValue)) {
            return encryptedValue;
        }

        // 关键：如果不是加密数据，直接返回原值
        if (!isEncryptedData(encryptedValue)) {
            System.out.println("[debug] 跳过非加密数据: " + encryptedValue);
            return encryptedValue;
        }

        try {
            // 1. Base64 URL-Safe 解码
            String base64Str = encryptedValue
                    .replace('-', '+')
                    .replace('_', '/');

            int padLen = (4 - (base64Str.length() % 4)) % 4;
            base64Str += "=".repeat(padLen);

            byte[] raw = Base64.getDecoder().decode(base64Str);

            // 2. 检查长度
            if (raw.length < NONCE_BYTES) {
                throw new IllegalArgumentException("密文长度不足");
            }

            // 3. 分离 nonce 和密文
            byte[] nonce = new byte[NONCE_BYTES];
            byte[] ciphertext = new byte[raw.length - NONCE_BYTES];
            System.arraycopy(raw, 0, nonce, 0, NONCE_BYTES);
            System.arraycopy(raw, NONCE_BYTES, ciphertext, 0, ciphertext.length);

            // 4. 构造 IV
            byte[] iv = new byte[16];
            System.arraycopy(nonce, 0, iv, 0, NONCE_BYTES);

            // 5. AES-CTR 解密
            SecretKeySpec keySpec = new SecretKeySpec(masterKey, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv);

            Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding");
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);

            byte[] decrypted = cipher.doFinal(ciphertext);

            // 6. UTF-8 解码
            String result = new String(decrypted, StandardCharsets.UTF_8);

            // 7. 验证解密结果（可选）
            if (!StringUtils.hasText(result)) {
                System.err.println("[warn] 解密结果为空，可能密钥错误");
            }

            return result;

        } catch (Exception e) {
            // 解密失败时返回原值，而不是抛出异常
            System.err.println("[warn] 解密失败，保留原值: " + encryptedValue + ", 原因: " + e.getMessage());
            return encryptedValue;
        }
    }

    /**
     * 解密 SuccessDataItemDto 列表中的加密字段
     *
     * @param dtoList 需要解密的 DTO 列表
     * @throws Exception 解密失败时抛出异常
     */
    public static void decryptDtoList(List<SuccessDataItemDto> dtoList) throws Exception {
        if (dtoList == null || dtoList.isEmpty()) {
            return;
        }

        int decryptedCount = 0;
        int skippedCount = 0;

        for (SuccessDataItemDto dto : dtoList) {
            try {
                // 解密 ISBN
                if (StringUtils.hasText(dto.getIsbn())) {
                    try {
                        dto.setIsbn(decryptField(dto.getIsbn()));
                        decryptedCount++;
                    } catch (Exception e) {
                        skippedCount++;
                        System.err.println("[warn] ISBN 解密失败: " + e.getMessage());
                    }
                }

                // 解密商品编码
                if (StringUtils.hasText(dto.getGoodsCode())) {
                    try {
                        dto.setGoodsCode(decryptField(dto.getGoodsCode()));
                        decryptedCount++;
                    } catch (Exception e) {
                        skippedCount++;
                        System.err.println("[warn] 商品编码 解密失败: " + e.getMessage());
                    }
                }

                // 解密商品名称
                if (StringUtils.hasText(dto.getTitle())) {
                    try {
                        dto.setTitle(decryptField(dto.getTitle()));
                        decryptedCount++;
                    } catch (Exception e) {
                        skippedCount++;
                        System.err.println("[warn] 商品名称 解密失败: " + e.getMessage());
                    }
                }

                // 解密规格编码
                if (StringUtils.hasText(dto.getSkuCode())) {
                    try {
                        dto.setSkuCode(decryptField(dto.getSkuCode()));
                        decryptedCount++;
                    } catch (Exception e) {
                        skippedCount++;
                        System.err.println("[warn] 规格编码 解密失败: " + e.getMessage());
                    }
                }

            } catch (Exception e) {
                System.err.println("[warn] 处理 DTO 时发生错误: " + e.getMessage());
            }
        }

        System.out.println("解密完成：解密 " + decryptedCount + " 个字段，跳过 " + skippedCount + " 个字段");
    }

    /**
     * 判断字符串是否为加密数据
     * 特征：包含Base64字符、长度>12、不是纯数字或纯字母
     */
    private static boolean isEncryptedData(String value) {
        if (!StringUtils.hasText(value)) {
            return false;
        }

        // 长度至少大于12字节（8字节nonce + 至少4字节密文）
        if (value.length() < 12) {
            return false;
        }

        // 纯数字的ISBN不是加密数据
        if (value.matches("\\d+")) {
            return false;
        }

        // 纯字母（如书名）不是加密数据
        if (value.matches("[a-zA-Z\\s\\u4e00-\\u9fa5]+")) {
            return false;
        }

        // 包含Base64特征字符
        return value.matches("^[A-Za-z0-9+/_-]+=*$");
    }


    /**
     * 获取主密钥指纹（用于验证）
     *
     * @return 密钥 SHA-256 前8位
     */
    public static String getKeyFingerprint() {
        try {
            java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(masterKey);
            StringBuilder hexString = new StringBuilder();
            for (int i = 0; i < Math.min(4, hash.length); i++) {
                String hex = Integer.toHexString(0xff & hash[i]);
                if (hex.length() == 1) hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (Exception e) {
            return "unknown";
        }
    }

    /**
     * 测试方法：验证解密功能
     */
    public static void main(String[] args) {
        System.out.println("主密钥指纹: " + getKeyFingerprint());
        System.out.println("预期指纹: 63c70bdd");

        // 测试用例：使用第一行数据的加密值
        String testIsbn = "m4Z6uhZiuc5-lDmv6p97FglNap0u";
        String testGoodsCode = "m4Z6uhZiuc5-lDmv6p97FglNap0u";
        String testTitle = "中学教材全练：九年级化学";
        String testSkuCode = "y4P9HTM8ThQ1BD7to7mC-4vhK-OI36Jh7Q";

        try {
            System.out.println("\n测试解密:");
            System.out.println("原始 ISBN: " + testIsbn);
            // 注意：这里测试需要的是加密后的数据，示例中的是明文，实际使用时会自动解密
        } catch (Exception e) {
            System.err.println("测试失败: " + e.getMessage());
        }
    }
}