using Backend.Domain;
using Backend.Security;
using Backend.Data;

namespace Backend.Endpoints;

internal static class AdminEndpointConventions
{
    public static UserSession CurrentSession(HttpContext context) =>
        context.GetCurrentSession() ?? throw new InvalidOperationException("Admin session missing from request context.");

    public static async ValueTask<object?> RequirePermission(
        EndpointFilterInvocationContext context,
        EndpointFilterDelegate next,
        string permissionKey)
    {
        var session = CurrentSession(context.HttpContext);
        var db = context.HttpContext.RequestServices.GetRequiredService<AwardsDbContext>();
        if (!await AdminPermissionCatalog.HasPermissionAsync(db, session.Role, permissionKey, context.HttpContext.RequestAborted))
        {
            return Results.Json(
                new { message = $"Diese Admin-Aktion braucht die Berechtigung '{permissionKey}'." },
                statusCode: StatusCodes.Status403Forbidden);
        }

        return await next(context);
    }

    public static async ValueTask<object?> RequireWritePermission(
        EndpointFilterInvocationContext context,
        EndpointFilterDelegate next,
        string permissionKey)
    {
        var session = CurrentSession(context.HttpContext);
        if (AdminRoles.Normalize(session.Role) == AdminRoles.OrganizationTeam)
        {
            return Results.Json(
                new { message = "Organisation Team hat fuer diesen Bereich nur Leserechte." },
                statusCode: StatusCodes.Status403Forbidden);
        }

        return await RequirePermission(context, next, permissionKey);
    }

    public static async ValueTask<object?> RequireAnyPermission(
        EndpointFilterInvocationContext context,
        EndpointFilterDelegate next,
        string[] permissionKeys)
    {
        var session = CurrentSession(context.HttpContext);
        var db = context.HttpContext.RequestServices.GetRequiredService<AwardsDbContext>();
        if (!await AdminPermissionCatalog.HasAnyPermissionAsync(db, session.Role, permissionKeys, context.HttpContext.RequestAborted))
        {
            return Results.Json(
                new { message = "Diese Admin-Aktion braucht eine passende Rollenberechtigung." },
                statusCode: StatusCodes.Status403Forbidden);
        }

        return await next(context);
    }
}
