using FluentValidation;

namespace SatelliteProvider.Api.Validators;

// AZ-795: shared validation infrastructure. A generic IEndpointFilter that
// resolves IValidator<T> from DI for the first argument of type T in the
// invoked endpoint and returns RFC 7807 ValidationProblemDetails (HTTP 400)
// with a structured `errors` map when the validator rejects. When validation
// passes, the filter forwards to the next stage unchanged.
//
// The filter is generic per request type; per-endpoint wire-up is done via
// `RouteHandlerBuilder.WithValidation<T>()` (see ValidationEndpointFilterExtensions).
// Per AZ-795 Outcome: callers must NOT need per-endpoint try/catch boilerplate;
// the filter provides the uniform error contract documented in
// `_docs/02_document/contracts/api/error-shape.md`.
public sealed class ValidationEndpointFilter<T> : IEndpointFilter where T : class
{
    public async ValueTask<object?> InvokeAsync(
        EndpointFilterInvocationContext context,
        EndpointFilterDelegate next)
    {
        var argument = context.Arguments.OfType<T>().FirstOrDefault();
        if (argument is null)
        {
            return await next(context);
        }

        var validator = context.HttpContext.RequestServices.GetService<IValidator<T>>();
        if (validator is null)
        {
            return await next(context);
        }

        var result = await validator.ValidateAsync(argument, context.HttpContext.RequestAborted);
        if (!result.IsValid)
        {
            return Results.ValidationProblem(result.ToDictionary());
        }

        return await next(context);
    }
}
