using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.Extensions.DependencyInjection;
using ZB.MOM.WW.Secrets.Abstractions;

namespace ZB.MOM.WW.Secrets.Ui;

/// <summary>
/// Resolves the principal to record as the audit <c>Actor</c> for a UI-driven secret mutation or
/// reveal. The resolution order is: an explicitly wired <see cref="ISecretActorAccessor"/> (if the
/// host registered one and it reports a non-blank actor); otherwise the authenticated user's
/// <see cref="System.Security.Principal.IIdentity.Name"/> from the cascading authentication state;
/// otherwise the literal <c>"unknown"</c> so an action is never attributed to a blank actor.
/// </summary>
internal static class SecretActorResolver
{
    /// <summary>The fallback actor used when no accessor and no authenticated identity name is available.</summary>
    public const string Unknown = "unknown";

    /// <summary>
    /// Resolves the audit actor. Never returns <c>null</c> or blank.
    /// </summary>
    /// <param name="services">The component's service provider, used to optionally resolve an <see cref="ISecretActorAccessor"/>.</param>
    /// <param name="authState">The cascading authentication-state task, or <c>null</c> if unavailable.</param>
    /// <returns>The resolved actor identity string.</returns>
    public static async Task<string> ResolveAsync(IServiceProvider services, Task<AuthenticationState>? authState)
    {
        string? fromAccessor = services.GetService<ISecretActorAccessor>()?.CurrentActor;
        if (!string.IsNullOrWhiteSpace(fromAccessor))
        {
            return fromAccessor;
        }

        if (authState is not null)
        {
            AuthenticationState state = await authState.ConfigureAwait(false);
            string? name = state.User.Identity?.Name;
            if (!string.IsNullOrWhiteSpace(name))
            {
                return name;
            }
        }

        return Unknown;
    }
}
