namespace ClaudeDo.Releases.Tests;

public class VersionComparerTests
{
    [Theory]
    [InlineData("0.2.0", "0.1.0", true, false)]
    [InlineData("0.2.0", "0.2.0", false, false)]
    [InlineData("0.1.0", "0.2.0", false, false)]
    [InlineData("v0.2.0", "0.1.0", true, false)]
    [InlineData("0.2.0", "v0.1.0", true, false)]
    [InlineData("1.0.0.0", "0.99.99.99", true, false)]
    // Prerelease and build-metadata suffixes are stripped to the numeric core
    // before comparing (System.Version can't parse them otherwise).
    [InlineData("0.2.0-beta", "0.1.0", true, false)]
    [InlineData("0.2.0", "0.1.0-alpha", true, false)]
    [InlineData("1.2.0", "1.0.2-alpha", true, false)]                       // real-world: installed 1.0.2-alpha -> 1.2.0
    [InlineData("v1.0.2-alpha+1c764dae", "1.0.0", true, false)]             // v-prefix + prerelease + build metadata combined
    [InlineData("1.0.2-alpha+abc", "1.0.2-alpha", false, false)]           // same core -> not newer
    [InlineData("1.2.0-rc1", "1.2.0", false, false)]                       // prerelease of an already-installed release
    // A dev build sitting on main computes a MinVer prerelease of its own guessed next
    // version, ahead of the last tag by core -> no banner (real-world repro: latest
    // published tag v2.9.0, worktree 14 commits ahead builds "2.9.1-alpha.0.14+sha").
    [InlineData("2.9.0", "2.9.1-alpha.0.14", false, false)]
    // A genuine new release lands at exactly the version a running dev build had
    // already guessed -> the release must still win over the still-running prerelease.
    [InlineData("1.4.1", "1.4.1-alpha.0.12", true, false)]
    // An installed real release exactly matching the latest tag stays "up to date".
    [InlineData("1.4.1", "1.4.1", false, false)]
    public void Compare_ParseableVersions(string latest, string current, bool expectedNewer, bool expectedUnparseable)
    {
        var result = VersionComparer.Compare(latest, current);
        Assert.Equal(expectedNewer, result.IsNewer);
        Assert.Equal(expectedUnparseable, result.Unparseable);
    }

    [Theory]
    [InlineData("garbage", "0.1.0")]
    [InlineData("0.2.0", "garbage")]
    [InlineData("", "0.1.0")]
    public void Compare_UnparseableReturnsNotNewer(string latest, string current)
    {
        var result = VersionComparer.Compare(latest, current);
        Assert.False(result.IsNewer);
        Assert.True(result.Unparseable);
    }
}
