using ScadaLink.Commons.Types.InboundApi;

namespace ScadaLink.Commons.Entities.InboundApi;

/// <summary>
/// An inbound-API bearer credential. Per ConfigurationDatabase-012 the plaintext key
/// is never persisted: the entity stores only <see cref="KeyHash"/>, a deterministic
/// keyed hash of the key (HMAC-SHA256 with a server-side pepper). The plaintext is
/// generated at creation, shown to the operator exactly once, and then discarded.
/// </summary>
public class ApiKey
{
    public int Id { get; set; }
    public string Name { get; set; }

    /// <summary>
    /// Deterministic keyed hash of the API key value. This is the only form of the
    /// credential persisted; the plaintext key is never stored. Authentication hashes
    /// the presented candidate with the same scheme and compares against this value.
    /// </summary>
    public string KeyHash { get; set; }

    public bool IsEnabled { get; set; }

    /// <summary>
    /// Creates an API key from a plaintext value, immediately hashing it with the
    /// unpeppered default hasher (<see cref="ApiKeyHasher.Default"/>) so the entity
    /// never holds the plaintext. Production code paths that have a configured pepper
    /// should use <see cref="FromHash(string, string)"/> with a peppered hash instead.
    /// </summary>
    public ApiKey(string name, string keyValue)
    {
        Name = name ?? throw new ArgumentNullException(nameof(name));
        if (keyValue is null) throw new ArgumentNullException(nameof(keyValue));
        KeyHash = ApiKeyHasher.Default.Hash(keyValue);
    }

    /// <summary>
    /// Parameterless constructor for the EF Core materializer. Application code uses
    /// <see cref="ApiKey(string, string)"/> or <see cref="FromHash(string, string)"/>.
    /// </summary>
    private ApiKey()
    {
        Name = string.Empty;
        KeyHash = string.Empty;
    }

    /// <summary>
    /// Creates an API key from an already-computed key hash. Used by the creation
    /// path, which generates a random key, hashes it with the configured (peppered)
    /// <see cref="IApiKeyHasher"/>, and stores only the resulting hash.
    /// </summary>
    public static ApiKey FromHash(string name, string keyHash)
    {
        return new ApiKey
        {
            Name = name ?? throw new ArgumentNullException(nameof(name)),
            KeyHash = keyHash ?? throw new ArgumentNullException(nameof(keyHash)),
        };
    }
}
