namespace StellaOps.Feedser.Merge.Comparers;

using System.Diagnostics.CodeAnalysis;
using Semver;

/// <summary>
/// Provides helpers to interpret introduced/fixed/lastAffected SemVer ranges and compare versions.
/// </summary>
public static class SemanticVersionRangeResolver
{
    public static bool TryParse(string? value, [NotNullWhen(true)] out SemVersion? result)
        => SemVersion.TryParse(value, SemVersionStyles.Any, out result);

    public static SemVersion Parse(string value)
        => SemVersion.Parse(value, SemVersionStyles.Any);

    /// <summary>
    /// Resolves the effective start and end versions using introduced/fixed/lastAffected semantics.
    /// </summary>
    public static (SemVersion? introduced, SemVersion? exclusiveUpperBound, SemVersion? inclusiveUpperBound) ResolveWindows(
        string? introduced,
        string? fixedVersion,
        string? lastAffected)
    {
        var introducedVersion = TryParse(introduced, out var parsedIntroduced) ? parsedIntroduced : null;
        var fixedVersionParsed = TryParse(fixedVersion, out var parsedFixed) ? parsedFixed : null;
        var lastAffectedVersion = TryParse(lastAffected, out var parsedLast) ? parsedLast : null;

        SemVersion? exclusiveUpper = null;
        SemVersion? inclusiveUpper = null;

        if (fixedVersionParsed is not null)
        {
            exclusiveUpper = fixedVersionParsed;
        }
        else if (lastAffectedVersion is not null)
        {
            inclusiveUpper = lastAffectedVersion;
            exclusiveUpper = NextPatch(lastAffectedVersion);
        }

        return (introducedVersion, exclusiveUpper, inclusiveUpper);
    }


    public static int Compare(string? left, string? right)
    {
        var leftParsed = TryParse(left, out var leftSemver);
        var rightParsed = TryParse(right, out var rightSemver);

        if (leftParsed && rightParsed)
        {
            return SemVersion.CompareSortOrder(leftSemver, rightSemver);
        }

        if (leftParsed)
        {
            return 1;
        }

        if (rightParsed)
        {
            return -1;
        }

        return string.Compare(left, right, StringComparison.Ordinal);
    }

    private static SemVersion NextPatch(SemVersion version)
    {
        return new SemVersion(version.Major, version.Minor, version.Patch + 1);
    }
}
