using System.Reflection;
using FluentAssertions;
using SatelliteProvider.Common.Configs;
using SatelliteProvider.Common.DTO;
using SatelliteProvider.Common.Utils;

namespace SatelliteProvider.Tests;

public class GeoUtilsRefactorTests
{
    [Fact]
    public void GeoUtils_DoesNotExposeCalculatePolygonDiagonalDistance_AZ380_AC1()
    {
        // Assert
        typeof(GeoUtils).GetMethod("CalculatePolygonDiagonalDistance").Should().BeNull(
            "AZ-380 deletes the dead alias method that simply forwarded to CalculateDistance");
    }

    [Theory]
    [InlineData("EarthRadiusMeters", 6378137d)]
    [InlineData("EarthEquatorialCircumferenceMeters", 40075016.686d)]
    [InlineData("MetersPerDegreeLatitude", 111000d)]
    public void GeoUtils_ExposesEarthConstantsAsPublicConst_AZ377_AC1(string fieldName, double expected)
    {
        // Arrange
        var field = typeof(GeoUtils).GetField(fieldName, BindingFlags.Public | BindingFlags.Static);

        // Assert
        field.Should().NotBeNull($"AZ-377 promotes {fieldName} to a public const on GeoUtils");
        field!.IsLiteral.Should().BeTrue($"{fieldName} must be a const so call sites can reference it without runtime cost");
        field.FieldType.Should().Be(typeof(double));
        field.GetRawConstantValue().Should().Be(expected, "AZ-377 forbids numerical drift from the previous literal");
    }

    [Fact]
    public void MapConfig_ExposesDefaultTileSizePixelsConst_AZ377_AC1()
    {
        // Arrange
        var field = typeof(MapConfig).GetField("DefaultTileSizePixels", BindingFlags.Public | BindingFlags.Static);

        // Assert
        field.Should().NotBeNull("AZ-377 introduces a const so DataAccess can reference the canonical pixel size without IOptions");
        field!.IsLiteral.Should().BeTrue();
        field.GetRawConstantValue().Should().Be(256);
        new MapConfig().TileSizePixels.Should().Be(MapConfig.DefaultTileSizePixels,
            "the instance default must remain wired to the const so config-bound consumers stay in sync");
    }

    [Fact]
    public void GeoUtils_HaversineProducesIdenticalResultAfterConstantRename_AZ377_AC2()
    {
        // Arrange
        var a = new GeoPoint(50.4501, 30.5234);
        var b = new GeoPoint(50.4501, 30.6234);

        // Act
        var d = GeoUtils.CalculateDistance(a, b);

        // Assert
        d.Should().BeApproximately(7090d, 5d,
            "renaming EARTH_RADIUS to EarthRadiusMeters must not change Haversine output");
    }
}
