using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;

public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
{
    private readonly ILogger<PermissionAuthorizationHandler> _logger;
    private readonly IHttpContextAccessor _http;
    private readonly ClinicalMetrics _metrics;

    public PermissionAuthorizationHandler(
        ILogger<PermissionAuthorizationHandler> logger,
        IHttpContextAccessor http,
        ClinicalMetrics metrics)
    {
        _logger = logger;
        _http = http;
        _metrics = metrics;
    }

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext context,
        PermissionRequirement requirement)
    {
        var roleClaim = context.User.FindFirst("clinical_role")?.Value;
        if (roleClaim is null)
        {
            LogAuthorizationFailure(context.User, "none", requirement.Permission);
            return Task.CompletedTask;
        }

        var role = ClinicalRoleExtensions.FromDbString(roleClaim);
        if (ClinicalRolePermissionMap.HasPermission(role, requirement.Permission))
        {
            context.Succeed(requirement);
        }
        else
        {
            LogAuthorizationFailure(context.User, roleClaim, requirement.Permission);
        }

        return Task.CompletedTask;
    }

    private void LogAuthorizationFailure(ClaimsPrincipal user, string role, string permission)
    {
        var username = user.FindFirst(ClaimTypes.Name)?.Value ?? "unknown";
        var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? "unknown";
        var endpoint = _http.HttpContext?.GetEndpoint()?.DisplayName ?? "unknown";

        _logger.LogWarning(
            "Authorization denied: user={User} (id={UserId}), role={Role}, " +
            "requiredPermission={Permission}, endpoint={Endpoint}",
            username, userId, role, permission, endpoint);

        _metrics.AuthorizationFailuresTotal.WithLabels(permission, role).Inc();
    }
}