using ScadaLink.Commons.Entities.InboundApi;
using ScadaLink.Commons.Types.InboundApi;

namespace ScadaLink.Commons.Tests.Entities;

/// <summary>
/// ConfigurationDatabase-012: the <see cref="ApiKey"/> entity must never carry the
/// plaintext bearer credential as a persisted field — only its deterministic hash.
/// </summary>
public class ApiKeyTests
{
    [Fact]
    public void ApiKey_HasNoPlaintextKeyValueProperty()
    {
        // The plaintext key is shown to the operator once at creation and is never
        // persisted. The entity must therefore expose KeyHash, not KeyValue.
        var properties = typeof(ApiKey).GetProperties().Select(p => p.Name).ToArray();

        Assert.DoesNotContain("KeyValue", properties);
        Assert.Contains("KeyHash", properties);
    }

    [Fact]
    public void Constructor_FromPlaintext_StoresHashNotPlaintext()
    {
        var key = new ApiKey("MES-Production", "the-secret-key-value");

        Assert.NotEqual("the-secret-key-value", key.KeyHash);
        Assert.Equal(ApiKeyHasher.Default.Hash("the-secret-key-value"), key.KeyHash);
    }

    [Fact]
    public void FromHash_StoresHashVerbatim()
    {
        var key = ApiKey.FromHash("RecipeManager-Dev", "precomputed-hash-value");

        Assert.Equal("RecipeManager-Dev", key.Name);
        Assert.Equal("precomputed-hash-value", key.KeyHash);
    }

    [Fact]
    public void Constructor_NullArguments_Throw()
    {
        Assert.Throws<ArgumentNullException>(() => new ApiKey(null!, "value"));
        Assert.Throws<ArgumentNullException>(() => new ApiKey("name", (string)null!));
        Assert.Throws<ArgumentNullException>(() => ApiKey.FromHash(null!, "hash"));
        Assert.Throws<ArgumentNullException>(() => ApiKey.FromHash("name", null!));
    }
}
