using Microsoft.VisualStudio.TestTools.UnitTesting;
using Strata.Base.Internal.Encryptors;
using System;
using System.Configuration;

namespace Strata.Base.Internal.Tests.Security
{
    [TestClass]
    public class UserGUIDEncryptionMethodTests
    {
        private const string TestUsername = "testuser";
        private const string TestOrgPin = "12345";
        private const string TestPassword = "password123";
        private static readonly Guid TestUserGuid = Guid.NewGuid();
        private const string TestSalt = "testsalt";
        private const string TestKey = "TestKey123";

        [TestInitialize]
        public void Setup()
        {
            // Set up the configuration key for testing
            var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            config.AppSettings.Settings.Remove("UserGuidEncryptionKey");
            config.AppSettings.Settings.Add("UserGuidEncryptionKey", TestKey);
            config.Save();
            ConfigurationManager.RefreshSection("appSettings");
        }

        [TestMethod]
        public void Encode_ReturnsNonEmptyString()
        {
            // Arrange
            var encryptor = new UserGUIDEncryptionMethod();

            // Act
            string result = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, TestUserGuid, TestSalt);

            // Assert
            Assert.IsFalse(string.IsNullOrEmpty(result), "Encoded result should not be empty");
        }

        [TestMethod]
        public void Encode_SameInputProducesSameOutput()
        {
            // Arrange
            var encryptor = new UserGUIDEncryptionMethod();

            // Act
            string result1 = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, TestUserGuid, TestSalt);
            string result2 = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, TestUserGuid, TestSalt);

            // Assert
            Assert.AreEqual(result1, result2, "Same input should produce same hash");
        }

        [TestMethod]
        public void Encode_DifferentPasswordsProduceDifferentOutputs()
        {
            // Arrange
            var encryptor = new UserGUIDEncryptionMethod();
            string differentPassword = "differentpassword123";

            // Act
            string result1 = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, TestUserGuid, TestSalt);
            string result2 = encryptor.Encode(TestUsername, TestOrgPin, differentPassword, TestUserGuid, TestSalt);

            // Assert
            Assert.AreNotEqual(result1, result2, "Different passwords should produce different hashes");
        }

        [TestMethod]
        public void Encode_DifferentUserGUIDsProduceDifferentOutputs()
        {
            // Arrange
            var encryptor = new UserGUIDEncryptionMethod();
            Guid differentGuid = Guid.NewGuid();

            // Act
            string result1 = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, TestUserGuid, TestSalt);
            string result2 = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, differentGuid, TestSalt);

            // Assert
            Assert.AreNotEqual(result1, result2, "Different UserGUIDs should produce different hashes");
        }

        [TestMethod]
        public void Encode_OutputIsBase64String()
        {
            // Arrange
            var encryptor = new UserGUIDEncryptionMethod();

            // Act
            string result = encryptor.Encode(TestUsername, TestOrgPin, TestPassword, TestUserGuid, TestSalt);

            // Assert
            try
            {
                Convert.FromBase64String(result);
            }
            catch (Exception ex)
            {
                Assert.Fail($"Result should be a valid Base64 string. Error: {ex.Message}");
            }
        }
    }
}
