using Baya.Infrastructure.CrossCutting.Seams;
using Microsoft.Extensions.Options;

namespace Baya.Test.Foundation;

public class SymmetricFieldEncryptorTests
{
    private static SymmetricFieldEncryptor CreateEncryptor()
    {
        var options = Options.Create(new SeamOptions
        {
            FieldEncryption = new FieldEncryptionOptions
            {
                Key = "unit-test-field-encryption-key",
                HashKey = "unit-test-hash-key"
            }
        });

        return new SymmetricFieldEncryptor(options);
    }

    [Fact]
    public void Decrypt_OfEncrypt_ReturnsOriginalPlaintext()
    {
        // Arrange
        var encryptor = CreateEncryptor();
        const string plaintext = "09123456789";

        // Act
        var cipher = encryptor.Encrypt(plaintext);
        var roundTripped = encryptor.Decrypt(cipher);

        // Assert
        Assert.NotEqual(plaintext, cipher);
        Assert.Equal(plaintext, roundTripped);
    }

    [Fact]
    public void Encrypt_SameInputTwice_ProducesDifferentCiphertext()
    {
        // Arrange — a random IV per call means ciphertext is not deterministic (semantic security).
        var encryptor = CreateEncryptor();
        const string plaintext = "IR820540102680020817909002";

        // Act
        var first = encryptor.Encrypt(plaintext);
        var second = encryptor.Encrypt(plaintext);

        // Assert
        Assert.NotEqual(first, second);
        Assert.Equal(plaintext, encryptor.Decrypt(first));
        Assert.Equal(plaintext, encryptor.Decrypt(second));
    }

    [Fact]
    public void Hash_IsDeterministic_ForLookups()
    {
        // Arrange
        var encryptor = CreateEncryptor();
        const string value = "IR820540102680020817909002";

        // Act
        var first = encryptor.Hash(value);
        var second = encryptor.Hash(value);

        // Assert
        Assert.Equal(first, second);
        Assert.NotEqual(value, first);
    }
}
