using System;
using System.Linq;
using StellaOps.Feedser.Models;
using Xunit;

namespace StellaOps.Feedser.Models.Tests;

public sealed class NormalizedVersionRuleTests
{
    [Fact]
    public void NormalizedVersions_AreDeduplicatedAndOrdered()
    {
        var recordedAt = DateTimeOffset.Parse("2025-01-05T00:00:00Z");
        var provenance = new AdvisoryProvenance("ghsa", "map", "GHSA-abc", recordedAt);
        var package = new AffectedPackage(
            type: AffectedPackageTypes.SemVer,
            identifier: "pkg:npm/example",
            versionRanges: Array.Empty<AffectedVersionRange>(),
            normalizedVersions: new[]
            {
                new NormalizedVersionRule("SemVer", "Exact", value: "1.0.0   "),
                new NormalizedVersionRule("semver", "range", min: "1.2.0", minInclusive: true, max: "2.0.0", maxInclusive: false, notes: "GHSA-abc"),
                new NormalizedVersionRule("semver", "range", min: "1.2.0", minInclusive: true, max: "2.0.0", maxInclusive: false, notes: "GHSA-abc"),
                new NormalizedVersionRule("semver", "gt", min: "0.9.0", minInclusive: false, notes: "  originating nvd "),
            },
            statuses: Array.Empty<AffectedPackageStatus>(),
            provenance: new[] { provenance });

        var normalized = package.NormalizedVersions.ToArray();
        Assert.Equal(3, normalized.Length);

        Assert.Collection(
            normalized,
            rule =>
            {
                Assert.Equal("semver", rule.Scheme);
                Assert.Equal("exact", rule.Type);
                Assert.Equal("1.0.0", rule.Value);
                Assert.Null(rule.Min);
                Assert.Null(rule.Max);
            },
            rule =>
            {
                Assert.Equal("semver", rule.Scheme);
                Assert.Equal("gt", rule.Type);
                Assert.Equal("0.9.0", rule.Min);
                Assert.False(rule.MinInclusive);
                Assert.Equal("originating nvd", rule.Notes);
            },
            rule =>
            {
                Assert.Equal("semver", rule.Scheme);
                Assert.Equal("range", rule.Type);
                Assert.Equal("1.2.0", rule.Min);
                Assert.True(rule.MinInclusive);
                Assert.Equal("2.0.0", rule.Max);
                Assert.False(rule.MaxInclusive);
                Assert.Equal("GHSA-abc", rule.Notes);
            });
    }

    [Fact]
    public void NormalizedVersionRule_NormalizesTypeSeparators()
    {
        var rule = new NormalizedVersionRule("semver", "tie_breaker", value: "1.2.3");
        Assert.Equal("tie-breaker", rule.Type);
    }
}
