using System;
using System.IO;
using System.Security.Cryptography;
using Havit.Extensions.DependencyInjection.Abstractions;
using Microsoft.Extensions.Options;

namespace DiplomovaPrace.Services.Security
{
	[Service]
	public class CryptographyService : ICryptographyService
	{
		private readonly AesConfiguration aesConfiguration;

		private static readonly byte[] initVector = { 0x35, 0xfd, 0x11, 0xfb, 0x0e, 0x75, 0x8a, 0xb2, 0xa0, 0xa3, 0x68, 0x1f, 0x69, 0xd6, 0xaa, 0xb4 };

		public CryptographyService(IOptions<AesConfiguration> aesConfiguration)
		{
			this.aesConfiguration = aesConfiguration.Value;
		}

		public string Decript(byte[] encryptedText)
		{
			string plainText;

			using (Aes aesCrypto = Aes.Create())
			{
				aesCrypto.Key = GetKey();
				aesCrypto.IV = initVector;

				ICryptoTransform decryptor = aesCrypto.CreateDecryptor(aesCrypto.Key, aesCrypto.IV);

				using MemoryStream memoryStream = new(encryptedText);
				using CryptoStream cryptoStream = new(memoryStream, decryptor, CryptoStreamMode.Read);
				using StreamReader streamReader = new(cryptoStream);
				try
				{
					plainText = streamReader.ReadToEnd();
				}
				catch (Exception)
				{
					return "";
				}
			}

			return plainText;
		}

		public byte[] Encrypt(string plainText)
		{
			byte[] encrypted;

			using (Aes aesCrypto = Aes.Create())
			{
				aesCrypto.Key = GetKey();
				aesCrypto.IV = initVector;

				ICryptoTransform encryptor = aesCrypto.CreateEncryptor(aesCrypto.Key, aesCrypto.IV);

				using MemoryStream memoryStream = new();
				using (CryptoStream cryptoStream = new(memoryStream, encryptor, CryptoStreamMode.Write))
				using (StreamWriter streamWriter = new(cryptoStream))
				{
					streamWriter.Write(plainText);
				}

				encrypted = memoryStream.ToArray();
			}

			return encrypted;
		}

		private byte[] GetKey()
		{
			string key = aesConfiguration.Key;

			if (string.IsNullOrWhiteSpace(key))
			{
				throw new ApplicationException("Šifrovací klíč nenalezen. (Aes:Key)");
			}

			return Convert.FromBase64String(key);
		}
	}
}
