using System.Runtime.Versioning;
using System.Security.Cryptography;
using ZB.MOM.WW.Secrets.Abstractions;

namespace ZB.MOM.WW.Secrets.MasterKey;

/// <summary>
/// Resolves the master key (KEK) by unprotecting a DPAPI-sealed blob file at
/// <see cref="MasterKeyOptions.FilePath"/> under the current-user scope. Windows-only.
/// </summary>
/// <remarks>
/// The file must contain the ciphertext produced by
/// <see cref="ProtectedData.Protect(byte[], byte[], DataProtectionScope)"/> for the 32-byte key.
/// The blob is read and unprotected fresh on every call. On a non-Windows OS
/// <see cref="ResolveKeyBytes"/> throws <see cref="PlatformNotSupportedException"/>.
/// </remarks>
[SupportedOSPlatform("windows")]
public sealed class DpapiMasterKeyProvider : MasterKeyProviderBase
{
    /// <summary>Creates the provider bound to <paramref name="options"/>.</summary>
    /// <param name="options">The master-key configuration (requires <see cref="MasterKeyOptions.FilePath"/>).</param>
    public DpapiMasterKeyProvider(MasterKeyOptions options) : base(options)
    {
    }

    /// <inheritdoc />
    protected override byte[] ResolveKeyBytes()
    {
        if (!OperatingSystem.IsWindows())
        {
            throw new PlatformNotSupportedException(
                "DPAPI master-key protection is only supported on Windows.");
        }

        string? path = Options.FilePath;
        if (string.IsNullOrEmpty(path))
        {
            throw new MasterKeyUnavailableException("DPAPI master key file path is not configured.");
        }

        if (!File.Exists(path))
        {
            throw new MasterKeyUnavailableException($"DPAPI master key file '{path}' does not exist.");
        }

        byte[] blob = File.ReadAllBytes(path);
        try
        {
            return ProtectedData.Unprotect(blob, optionalEntropy: null, DataProtectionScope.CurrentUser);
        }
        catch (CryptographicException ex)
        {
            throw new MasterKeyUnavailableException(
                $"Failed to DPAPI-unprotect master key file '{path}': {ex.Message}");
        }
    }
}
