using FluentValidation;
using SatelliteProvider.Common.DTO;

namespace SatelliteProvider.Api.Validators;

// AZ-808: FluentValidation rules for POST /api/satellite/request.
// Wired through ValidationEndpointFilter<RequestRegionRequest> at endpoint
// registration time (.WithValidation<RequestRegionRequest>() in Program.cs).
// Failures are converted to RFC 7807 ValidationProblemDetails per
// _docs/02_document/contracts/api/error-shape.md v1.0.0.
//
// Required-field detection is handled at the deserializer level via
// [JsonRequired] on RequestRegionRequest properties plus
// JsonSerializerOptions.UnmappedMemberHandling.Disallow (AZ-795). This
// validator covers the post-deserialization business rules: non-zero Id,
// lat/lon/sizeMeters/zoomLevel range constraints.
public sealed class RegionRequestValidator : AbstractValidator<RequestRegionRequest>
{
    private const double MinLat = -90.0;
    private const double MaxLat = 90.0;
    private const double MinLon = -180.0;
    private const double MaxLon = 180.0;
    private const double MinSizeMeters = 100.0;
    private const double MaxSizeMeters = 10000.0;
    private const int MinZoom = 0;
    private const int MaxZoom = 22;

    public RegionRequestValidator()
    {
        RuleFor(req => req.Id)
            .NotEmpty()
            .WithMessage("`id` must be a non-zero GUID (the caller's idempotency key).");

        RuleFor(req => req.Lat)
            .InclusiveBetween(MinLat, MaxLat)
            .WithMessage($"`lat` must be between {MinLat} and {MaxLat}.");

        RuleFor(req => req.Lon)
            .InclusiveBetween(MinLon, MaxLon)
            .WithMessage($"`lon` must be between {MinLon} and {MaxLon}.");

        RuleFor(req => req.SizeMeters)
            .InclusiveBetween(MinSizeMeters, MaxSizeMeters)
            .WithMessage($"`sizeMeters` must be between {MinSizeMeters} and {MaxSizeMeters} meters.");

        RuleFor(req => req.ZoomLevel)
            .InclusiveBetween(MinZoom, MaxZoom)
            .WithMessage($"`zoomLevel` must be between {MinZoom} and {MaxZoom} (slippy-map range).");
    }
}
