using System.Security.Cryptography;


namespace ToolsServices
{
    #region classe statique CryptoConfig
    public static class CryptoConfig
    {
        #region Variables publiques
        public static readonly byte[] Key;
        public static readonly byte[] IV;
        #endregion

        #region Variables locales
        private static readonly string File_KEY = "aes_key.bin";
        private static readonly string File_IV = "aes_iv.bin";
        #endregion

        #region Constructeur statique
        static CryptoConfig()
        {
            LoggerService.LogInfo("CryptoConfig");

            using var aes = Aes.Create();
            if (System.IO.File.Exists(File_KEY) && System.IO.File.Exists(File_IV))
            {
                Key = File.ReadAllBytes(File_KEY);
                IV = File.ReadAllBytes(File_IV);
            }
            else
            {
                Key = aes.Key;
                IV = aes.IV;

                File.WriteAllBytes(File_KEY, Key);
                File.WriteAllBytes(File_IV, IV);
            }
        }
        #endregion 
    }
    #endregion

    #region classe statique AesEncryption
    public static class AesEncryption
    {
        #region Méthodes publiques
        public static byte[] EncryptStringToBytes(string plainText, byte[] key, byte[] iv)
        {
            LoggerService.LogInfo("AesEncryption.EncryptStringToBytes");

            using Aes aesAlg = Aes.Create();
            aesAlg.Key = key;
            aesAlg.IV = iv;

            using var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            using var msEncrypt = new MemoryStream();
            using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            using (var swEncrypt = new StreamWriter(csEncrypt))
            {
                swEncrypt.Write(plainText);
            }

            return msEncrypt.ToArray();
        }

        public static string DecryptStringFromBytes(byte[] cipherText, byte[] key, byte[] iv)
        {
            LoggerService.LogDebug("AesEncryption.DecryptStringFromBytes");

            using Aes aesAlg = Aes.Create();
            aesAlg.Key = key;
            aesAlg.IV = iv;

            using var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
            using var msDecrypt = new MemoryStream(cipherText);
            using var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
            using var srDecrypt = new StreamReader(csDecrypt);
            return srDecrypt.ReadToEnd();
        }
        #endregion
    }
    #endregion 

    #region classe statique CryptageService
    public static class CryptageService
    {
        #region Méthodes publiques
        public static string EncryptData(string clairString)
        {
            LoggerService.LogDebug("CryptageService.EncryptData");

            byte[] encrypted = AesEncryption.EncryptStringToBytes(clairString, CryptoConfig.Key, CryptoConfig.IV);
            return Convert.ToBase64String(encrypted);
        }

        public static string DecryptData(string encryptedString)
        {
            LoggerService.LogDebug("CryptageService.DecryptData");

            try
            {
                byte[] encryptedFromFile = Convert.FromBase64String(encryptedString);
                string decrypted = AesEncryption.DecryptStringFromBytes(encryptedFromFile, CryptoConfig.Key, CryptoConfig.IV);
                return decrypted;
            }
            catch (Exception ex)
            {
                LoggerService.LogError($"CryptageService.DecryptData {ex.Message}");
                return ex.Message;
            }
        }
        #endregion

    }
    #endregion
}
