using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;

namespace ROLAC.API.Authorization;

/// <summary>
/// Materializes <c>PERM:&lt;module&gt;:&lt;action&gt;</c> policies on demand so we never
/// have to register every module/action combination at startup. Any other policy name
/// (including the default and <c>Roles=</c> policies) is delegated to the framework's
/// default provider, so existing <c>[Authorize(Roles=...)]</c> usages keep working.
/// </summary>
public class PermissionPolicyProvider : IAuthorizationPolicyProvider
{
    private readonly DefaultAuthorizationPolicyProvider _fallback;

    public PermissionPolicyProvider(IOptions<AuthorizationOptions> options)
        => _fallback = new DefaultAuthorizationPolicyProvider(options);

    public Task<AuthorizationPolicy> GetDefaultPolicyAsync() => _fallback.GetDefaultPolicyAsync();

    public Task<AuthorizationPolicy?> GetFallbackPolicyAsync() => _fallback.GetFallbackPolicyAsync();

    public Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
    {
        var parsed = HasPermissionAttribute.Parse(policyName);
        if (parsed is null)
            return _fallback.GetPolicyAsync(policyName);

        var policy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddRequirements(new PermissionRequirement(parsed.Value.Module, parsed.Value.Action))
            .Build();

        return Task.FromResult<AuthorizationPolicy?>(policy);
    }
}
