using Grpc.Core;
using ZB.MOM.WW.GalaxyRepository.Grpc;
using ZB.MOM.WW.MxGateway.Server.Security.Authentication;

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

/// <summary>Scopes Galaxy browse results to the calling API key's BrowseSubtrees constraint.</summary>
public sealed class GatewayBrowseScopeProvider(IGatewayRequestIdentityAccessor identityAccessor)
    : IGalaxyBrowseScopeProvider
{
    /// <summary>Resolves the Galaxy browse subtrees the calling API key is scoped to, from the ambient request identity.</summary>
    /// <param name="context">The gRPC server call context for the in-flight browse request.</param>
    /// <returns>The caller's configured browse subtrees, or <see langword="null"/>/empty when the caller is unscoped (full hierarchy).</returns>
    public IReadOnlyList<string>? ResolveBrowseSubtrees(ServerCallContext context)
    {
        // Invariant: the caller identity is the ambient one pushed by
        // GatewayGrpcAuthorizationInterceptor earlier in this same call. That interceptor is
        // registered globally and therefore runs before the library's galaxy service, so
        // Current is populated for any authenticated galaxy RPC. If it is somehow absent we
        // return empty BrowseSubtrees, which the library treats as "no scoping" (full
        // hierarchy) — safe only because the global interceptor has already authenticated and
        // authorized the request first. Do not reorder the interceptor without revisiting this.
        ApiKeyConstraints constraints = identityAccessor.Current?.EffectiveConstraints ?? ApiKeyConstraints.Empty;
        return constraints.BrowseSubtrees;
    }
}
