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> processingConfig)
    {
        ArgumentNullException.ThrowIfNull(processingConfig);
        _latLonTolerance = processingConfig.Value.LatLonTolerance;
    }

    public void Validate(CreateRouteRequest request)
    {
        ArgumentNullException.ThrowIfNull(request);

        var errors = new List<string>();

        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<string> 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");
        }
    }
}
