using ZB.MOM.WW.MxGateway.Server.Security.Authentication;

namespace ZB.MOM.WW.MxGateway.Server.Security.Authorization;

public sealed class GatewayRequestIdentityAccessor : IGatewayRequestIdentityAccessor
{
    private readonly AsyncLocal<ApiKeyIdentity?> currentIdentity = new();

    /// <summary>Gets the current request identity.</summary>
    public ApiKeyIdentity? Current => currentIdentity.Value;

    /// <summary>Sets the current identity and returns a scope that restores the previous identity.</summary>
    /// <param name="identity">The identity to push.</param>
    /// <returns>Disposable scope.</returns>
    public IDisposable Push(ApiKeyIdentity identity)
    {
        ArgumentNullException.ThrowIfNull(identity);

        ApiKeyIdentity? previousIdentity = currentIdentity.Value;
        currentIdentity.Value = identity;

        return new IdentityScope(this, previousIdentity);
    }

    private sealed class IdentityScope(
        GatewayRequestIdentityAccessor accessor,
        ApiKeyIdentity? previousIdentity) : IDisposable
    {
        private bool disposed;

        /// <summary>Restores the previous identity.</summary>
        public void Dispose()
        {
            if (disposed)
            {
                return;
            }

            accessor.currentIdentity.Value = previousIdentity;
            disposed = true;
        }
    }
}
