using Microsoft.Extensions.Options; using SatelliteProvider.Common.Configs; using SatelliteProvider.Common.DTO; namespace SatelliteProvider.Services.RouteManagement; public class RouteValidator { private readonly double _latLonTolerance; public RouteValidator(IOptions processingConfig) { ArgumentNullException.ThrowIfNull(processingConfig); _latLonTolerance = processingConfig.Value.LatLonTolerance; } public void Validate(CreateRouteRequest request) { ArgumentNullException.ThrowIfNull(request); var errors = new List(); if (request.Points is null || request.Points.Count < 2) { errors.Add("Route must have at least 2 points"); } if (request.RegionSizeMeters < 100 || request.RegionSizeMeters > 10000) { errors.Add("Region size must be between 100 and 10000 meters"); } if (string.IsNullOrWhiteSpace(request.Name)) { errors.Add("Route name is required"); } if (request.Geofences?.Polygons is { Count: > 0 } polygons) { for (int i = 0; i < polygons.Count; i++) { ValidatePolygon(polygons[i], errors); } } if (errors.Count > 0) { throw new ArgumentException(string.Join("; ", errors)); } } private void ValidatePolygon(GeofencePolygon polygon, List errors) { if (polygon.NorthWest is null || polygon.SouthEast is null) { errors.Add("Geofence polygon coordinates are required"); return; } var nw = polygon.NorthWest; var se = polygon.SouthEast; if ((Math.Abs(nw.Lat) < _latLonTolerance && Math.Abs(nw.Lon) < _latLonTolerance) || (Math.Abs(se.Lat) < _latLonTolerance && Math.Abs(se.Lon) < _latLonTolerance)) { errors.Add("Geofence polygon coordinates cannot be (0,0)"); } if (nw.Lat < -90 || nw.Lat > 90 || se.Lat < -90 || se.Lat > 90 || nw.Lon < -180 || nw.Lon > 180 || se.Lon < -180 || se.Lon > 180) { errors.Add("Geofence polygon coordinates must be valid (lat: -90 to 90, lon: -180 to 180)"); } if (nw.Lat <= se.Lat) { errors.Add("Geofence northWest latitude must be greater than southEast latitude"); } } }