using StellaOps.Feedser.Merge.Comparers;
using StellaOps.Feedser.Normalization.Distro;

namespace StellaOps.Feedser.Merge.Tests;

public sealed class DebianEvrComparerTests
{
    [Theory]
    [InlineData("1:1.2.3-1", 1, "1.2.3", "1")]
    [InlineData("1.2.3-1", 0, "1.2.3", "1")]
    [InlineData("2:4.5", 2, "4.5", "")]
    [InlineData("abc", 0, "abc", "")]
    public void TryParse_ReturnsComponents(string input, int expectedEpoch, string expectedVersion, string expectedRevision)
    {
        var success = DebianEvr.TryParse(input, out var evr);

        Assert.True(success);
        Assert.NotNull(evr);
        Assert.Equal(expectedEpoch, evr!.Epoch);
        Assert.Equal(expectedVersion, evr.Version);
        Assert.Equal(expectedRevision, evr.Revision);
        Assert.Equal(input, evr.Original);
    }

    [Theory]
    [InlineData("")]
    [InlineData(":1.0-1")]
    [InlineData("1:")]
    public void TryParse_InvalidInputs_ReturnFalse(string input)
    {
        var success = DebianEvr.TryParse(input, out var evr);

        Assert.False(success);
        Assert.Null(evr);
    }

    [Fact]
    public void Compare_PrefersHigherEpoch()
    {
        var lower = "0:2.0-1";
        var higher = "1:1.0-1";

        Assert.True(DebianEvrComparer.Instance.Compare(higher, lower) > 0);
    }

    [Fact]
    public void Compare_UsesVersionOrdering()
    {
        var lower = "0:1.2.3-1";
        var higher = "0:1.10.0-1";

        Assert.True(DebianEvrComparer.Instance.Compare(higher, lower) > 0);
    }

    [Fact]
    public void Compare_TildeRanksEarlier()
    {
        var prerelease = "0:1.0~beta1-1";
        var stable = "0:1.0-1";

        Assert.True(DebianEvrComparer.Instance.Compare(prerelease, stable) < 0);
    }

    [Fact]
    public void Compare_RevisionBreaksTies()
    {
        var first = "0:1.0-1";
        var second = "0:1.0-2";

        Assert.True(DebianEvrComparer.Instance.Compare(second, first) > 0);
    }

    [Fact]
    public void Compare_FallsBackToOrdinalForInvalid()
    {
        var left = "not-an-evr";
        var right = "also-not";

        var expected = Math.Sign(string.CompareOrdinal(left, right));
        var actual = Math.Sign(DebianEvrComparer.Instance.Compare(left, right));

        Assert.Equal(expected, actual);
    }
}
