using StellaOps.Feedser.Merge.Comparers;

namespace StellaOps.Feedser.Merge.Tests;

public sealed class SemanticVersionRangeResolverTests
{
    [Theory]
    [InlineData("1.2.3", true)]
    [InlineData("1.2.3-beta.1", true)]
    [InlineData("invalid", false)]
    [InlineData(null, false)]
    public void TryParse_ReturnsExpected(string? input, bool expected)
    {
        var success = SemanticVersionRangeResolver.TryParse(input, out var version);

        Assert.Equal(expected, success);
        Assert.Equal(expected, version is not null);
    }

    [Fact]
    public void Compare_ParsesSemanticVersions()
    {
        Assert.True(SemanticVersionRangeResolver.Compare("1.2.3", "1.2.2") > 0);
        Assert.True(SemanticVersionRangeResolver.Compare("1.2.3-beta", "1.2.3") < 0);
    }

    [Fact]
    public void Compare_UsesOrdinalFallbackForInvalid()
    {
        var left = "zzz";
        var right = "aaa";
        var expected = Math.Sign(string.CompareOrdinal(left, right));
        var actual = Math.Sign(SemanticVersionRangeResolver.Compare(left, right));

        Assert.Equal(expected, actual);
    }

    [Fact]
    public void ResolveWindows_WithFixedVersion_ComputesExclusiveUpper()
    {
        var (introduced, exclusive, inclusive) = SemanticVersionRangeResolver.ResolveWindows("1.0.0", "1.2.0", null);

        Assert.Equal(SemanticVersionRangeResolver.Parse("1.0.0"), introduced);
        Assert.Equal(SemanticVersionRangeResolver.Parse("1.2.0"), exclusive);
        Assert.Null(inclusive);
    }

    [Fact]
    public void ResolveWindows_WithLastAffectedOnly_ComputesInclusiveAndExclusive()
    {
        var (introduced, exclusive, inclusive) = SemanticVersionRangeResolver.ResolveWindows("1.0.0", null, "1.1.5");

        Assert.Equal(SemanticVersionRangeResolver.Parse("1.0.0"), introduced);
        Assert.Equal(SemanticVersionRangeResolver.Parse("1.1.6"), exclusive);
        Assert.Equal(SemanticVersionRangeResolver.Parse("1.1.5"), inclusive);
    }

    [Fact]
    public void ResolveWindows_WithNeither_ReturnsNullBounds()
    {
        var (introduced, exclusive, inclusive) = SemanticVersionRangeResolver.ResolveWindows(null, null, null);

        Assert.Null(introduced);
        Assert.Null(exclusive);
        Assert.Null(inclusive);
    }
}
