using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
namespace TakeoutSaaS.Module.Authorization.Policies;
/// <summary>
/// 权限策略提供者（按需动态构建策略）。
/// </summary>
public sealed class PermissionAuthorizationPolicyProvider(IOptions<AuthorizationOptions> options) : DefaultAuthorizationPolicyProvider(options)
{
    /// <summary>
    /// 权限策略名称前缀。
    /// </summary>
    public const string PolicyPrefix = "PERMISSION:";
    private readonly AuthorizationOptions _options = options.Value;
    /// <summary>
    /// 获取或构建指定名称的权限策略。
    /// </summary>
    /// <param name="policyName">策略名称。</param>
    /// <returns>匹配的授权策略。</returns>
    public override Task<AuthorizationPolicy?> GetPolicyAsync(string policyName)
    {
        // 1. 非权限策略走基类逻辑
        if (!policyName.StartsWith(PolicyPrefix, StringComparison.OrdinalIgnoreCase))
        {
            return base.GetPolicyAsync(policyName);
        }
        // 2. 复用已存在的策略
        var existingPolicy = _options.GetPolicy(policyName);
        if (existingPolicy != null)
        {
            return Task.FromResult<AuthorizationPolicy?>(existingPolicy);
        }
        // 3. 解析策略携带的权限列表
        var permissions = ParsePermissions(policyName);
        if (permissions.Length == 0)
        {
            return Task.FromResult<AuthorizationPolicy?>(null);
        }
        // 4. 动态构建策略并缓存
        var policy = new AuthorizationPolicyBuilder()
            .AddRequirements(new PermissionRequirement(permissions))
            .Build();
        _options.AddPolicy(policyName, policy);
        // 5. 返回构建好的策略
        return Task.FromResult<AuthorizationPolicy?>(policy);
    }
    /// <summary>
    /// 根据权限集合构建策略名称。
    /// </summary>
    /// <param name="permissions">权限标识集合。</param>
    /// <returns>策略名称。</returns>
    public static string BuildPolicyName(IEnumerable<string> permissions)
        => $"{PolicyPrefix}{string.Join('|', NormalizePermissions(permissions))}";
    private static string[] ParsePermissions(string policyName)
    {
        // 1. 拆分策略名称得到原始权限列表
        var raw = policyName[PolicyPrefix.Length..];
        // 2. 规范化并过滤权限
        return NormalizePermissions(raw.Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries));
    }
    private static string[] NormalizePermissions(IEnumerable<string> permissions)
        => [.. permissions
            .Where(p => !string.IsNullOrWhiteSpace(p))
            .Select(p => p.Trim())
            .Distinct(StringComparer.OrdinalIgnoreCase)];
}
