using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace SparkClient.Model.Helper;

public class AESHelper
{
    private static readonly int KeySize = 256; // AES-256
    private static readonly int BlockSize = 128; // AES 块大小

    /// <summary>
    /// 加密字符串
    /// </summary>
    /// <param name="plainText">明文</param>
    /// <param name="key">密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>加密后的 Base64 字符串</returns>
    public static string Encrypt(string plainText, string key = Common.AesKey, string iv = Common.AesIV)
    {
        using (var aes = CreateAes(key, iv))
        {
            var encryptor = aes.CreateEncryptor();
            var plainBytes = Encoding.UTF8.GetBytes(plainText);
            var cipherBytes = PerformCryptography(plainBytes, encryptor);
            return Convert.ToBase64String(cipherBytes);
        }
    }

    /// <summary>
    /// 解密字符串
    /// </summary>
    /// <param name="cipherText">密文(Base64 格式)</param>
    /// <param name="key">密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>解密后的明文</returns>
    public static string Decrypt(string cipherText, string key = Common.AesKey, string iv = Common.AesIV)
    {
        using (var aes = CreateAes(key, iv))
        {
            var decryptor = aes.CreateDecryptor();
            var cipherBytes = Convert.FromBase64String(cipherText);
            var plainBytes = PerformCryptography(cipherBytes, decryptor);
            return Encoding.UTF8.GetString(plainBytes);
        }
    }

    /// <summary>
    /// 加密字节数组
    /// </summary>
    /// <param name="plainBytes">明文字节数组</param>
    /// <param name="key">密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>加密后的字节数组</returns>
    public static byte[] Encrypt(byte[] plainBytes, string key = Common.AesKey, string iv = Common.AesIV)
    {
        using (var aes = CreateAes(key, iv))
        {
            var encryptor = aes.CreateEncryptor();
            return PerformCryptography(plainBytes, encryptor);
        }
    }

    /// <summary>
    /// 解密字节数组
    /// </summary>
    /// <param name="cipherBytes">密文字节数组</param>
    /// <param name="key">密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>解密后的字节数组</returns>
    public static byte[] Decrypt(byte[] cipherBytes, string key = Common.AesKey, string iv = Common.AesIV)
    {
        using (var aes = CreateAes(key, iv))
        {
            var decryptor = aes.CreateDecryptor();
            return PerformCryptography(cipherBytes, decryptor);
        }
    }

    /// <summary>
    /// 创建 AES 实例
    /// </summary>
    /// <param name="key">密钥</param>
    /// <param name="iv">初始化向量</param>
    /// <returns>AES 实例</returns>
    private static Aes CreateAes(string key = Common.AesKey, string iv = Common.AesIV)
    {
        var aes = Aes.Create();
        aes.KeySize = KeySize;
        aes.BlockSize = BlockSize;
        aes.Padding = PaddingMode.PKCS7;
        aes.Mode = CipherMode.CBC; // 使用 CBC 模式
        aes.Key = Encoding.UTF8.GetBytes(key.PadRight(KeySize / 8, '0')); // 密钥长度填充
        aes.IV = Encoding.UTF8.GetBytes(iv.PadRight(BlockSize / 8, '0')); // IV 长度填充
        return aes;
    }

    /// <summary>
    /// 执行加密或解密
    /// </summary>
    /// <param name="data">输入数据</param>
    /// <param name="cryptoTransform">加密或解密转换器</param>
    /// <returns>处理后的数据</returns>
    private static byte[] PerformCryptography(byte[] data, ICryptoTransform cryptoTransform)
    {
        using (var memoryStream = new MemoryStream())
        {
            using (var cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
            {
                cryptoStream.Write(data, 0, data.Length);
                cryptoStream.FlushFinalBlock();
                return memoryStream.ToArray();
            }
        }
    }
    public static string DecryptFile(string inputFile, string password)
    {
        var aes = Aes.Create();
        var pdb = new Rfc2898DeriveBytes(password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        aes.Key = pdb.GetBytes(32);
        aes.IV = pdb.GetBytes(16);
        StringBuilder sb = new StringBuilder();
        using (var fs = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
        {
            using (var cs = new CryptoStream(fs, aes.CreateDecryptor(), CryptoStreamMode.Read))
            {
                StreamReader sr = new StreamReader(cs);
                while (!sr.EndOfStream)
                {
                    sb.Append(sr.ReadLine());
                }
            }
        }
        return sb.ToString();
    }
}