namespace ClaudeDo.Releases;

public readonly record struct VersionCompareResult(bool IsNewer, bool Unparseable);

public static class VersionComparer
{
    public static VersionCompareResult Compare(string latest, string current)
    {
        var unparseable = !Version.TryParse(CoreVersion(latest), out var lv)
                        | !Version.TryParse(CoreVersion(current), out var cv);

        if (unparseable) return new VersionCompareResult(false, true);
        if (lv != cv) return new VersionCompareResult(lv > cv, false);

        // Same numeric core: a MinVer dev build sitting on main between two tags
        // reports a prerelease of its own guessed *next* version (e.g. after tag
        // v1.4.0, main computes "1.4.1-alpha.0.12" — already ahead of the tag by
        // core, handled above). But when a real release is tagged at exactly that
        // guessed version, the tag itself has no prerelease suffix while a still-
        // running dev build does — that dev build must still count as older, or a
        // genuine new release would be silently missed.
        var isNewer = HasPrerelease(current) && !HasPrerelease(latest);
        return new VersionCompareResult(isNewer, false);
    }

    // Reduce a tag/version to its numeric core: drop a leading "v", MinVer build
    // metadata ("+sha"), and any SemVer prerelease suffix ("-alpha") — none of
    // which System.Version can parse. So "v1.0.2-alpha+abc" -> "1.0.2".
    private static string CoreVersion(string value)
        => (value ?? "").TrimStart('v', 'V').Split('+')[0].Split('-')[0];

    private static bool HasPrerelease(string value)
        => (value ?? "").TrimStart('v', 'V').Split('+')[0].Contains('-');
}
