using System.Text.Json.Nodes;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi;
using Tiku.Api.Security;
using Tiku.Application.Security;

namespace Tiku.Api.OpenApi;

[AttributeUsage(AttributeTargets.Method)]
public sealed class PlatformOperationRiskAttribute(
    string riskLevel,
    string? approvalPolicyCode = null) : Attribute
{
    public string RiskLevel { get; } = riskLevel;
    public string? ApprovalPolicyCode { get; } = approvalPolicyCode;
}

internal sealed class PlatformOperationMetadataTransformer : IOpenApiOperationTransformer
{
    public Task TransformAsync(
        OpenApiOperation operation,
        OpenApiOperationTransformerContext context,
        CancellationToken cancellationToken)
    {
        var authorization = context.Description.ActionDescriptor.EndpointMetadata
            .OfType<EndpointAuthorizationMetadata>()
            .LastOrDefault();
        if (authorization?.Realm != "platform") return Task.CompletedTask;

        if (authorization.Permission is not null)
            operation.AddExtension("x-tiku-required-permission",
                new JsonNodeExtension(JsonValue.Create(authorization.Permission)));

        var declaredRisk = context.Description.ActionDescriptor.EndpointMetadata
            .OfType<PlatformOperationRiskAttribute>()
            .LastOrDefault();
        var riskLevel = declaredRisk?.RiskLevel ??
                        (authorization.Operation == CapabilityOperation.Read ? "low" : "medium");
        operation.AddExtension("x-tiku-risk-level", new JsonNodeExtension(JsonValue.Create(riskLevel)));
        if (declaredRisk?.ApprovalPolicyCode is not null)
            operation.AddExtension("x-tiku-approval-policy-code",
                new JsonNodeExtension(JsonValue.Create(declaredRisk.ApprovalPolicyCode)));

        return Task.CompletedTask;
    }
}