namespace SatelliteProvider.Api.Validators;

// AZ-811: endpoint filter that rejects any query-string parameter outside an
// allowed-set. ASP.NET model binding silently ignores unknown query params,
// which means typos (e.g. `?latitude=` after AZ-812's rename to `lat`) bind
// to the default value (0.0) and may produce a misleading 200 or a confusing
// out-of-range 400 from the value-validator. This filter catches the typo at
// the envelope level and returns a structured RFC 7807 ValidationProblemDetails
// with errors[<paramName>] = "Unknown query parameter ...", matching the
// shape produced by ValidationEndpointFilter<T> + GlobalExceptionHandler.
//
// Apply BEFORE ValidationEndpointFilter<T> so unknown-param errors precede
// range checks against the bound default value.
public sealed class RejectUnknownQueryParamsEndpointFilter : IEndpointFilter
{
    private readonly HashSet<string> _allowedKeys;

    public RejectUnknownQueryParamsEndpointFilter(IEnumerable<string> allowedKeys)
    {
        _allowedKeys = new HashSet<string>(allowedKeys, StringComparer.OrdinalIgnoreCase);
    }

    public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next)
    {
        var query = context.HttpContext.Request.Query;
        var unknown = query.Keys.Where(k => !_allowedKeys.Contains(k)).ToList();

        if (unknown.Count > 0)
        {
            var errors = unknown.ToDictionary(
                k => k,
                k => new[]
                {
                    $"Unknown query parameter `{k}`. Allowed: {string.Join(", ", _allowedKeys.Select(a => $"`{a}`"))}."
                });

            return Results.ValidationProblem(errors);
        }

        return await next(context);
    }
}
