using System;
using StellaOps.Feedser.Models;

namespace StellaOps.Feedser.Models.Tests;

public sealed class AffectedPackageStatusTests
{
    [Theory]
    [InlineData("Known_Affected", AffectedPackageStatusCatalog.KnownAffected)]
    [InlineData("KNOWN-NOT-AFFECTED", AffectedPackageStatusCatalog.KnownNotAffected)]
    [InlineData("Under Investigation", AffectedPackageStatusCatalog.UnderInvestigation)]
    [InlineData("Fixed", AffectedPackageStatusCatalog.Fixed)]
    [InlineData("Known not vulnerable", AffectedPackageStatusCatalog.KnownNotAffected)]
    [InlineData("Impacted", AffectedPackageStatusCatalog.Affected)]
    [InlineData("Not Vulnerable", AffectedPackageStatusCatalog.NotAffected)]
    [InlineData("Analysis in progress", AffectedPackageStatusCatalog.UnderInvestigation)]
    [InlineData("Patch Available", AffectedPackageStatusCatalog.Fixed)]
    [InlineData("Workaround available", AffectedPackageStatusCatalog.Mitigated)]
    [InlineData("Does Not Apply", AffectedPackageStatusCatalog.NotApplicable)]
    [InlineData("Awaiting fix", AffectedPackageStatusCatalog.Pending)]
    [InlineData("TBD", AffectedPackageStatusCatalog.Unknown)]
    public void Constructor_NormalizesStatus(string input, string expected)
    {
        var provenance = new AdvisoryProvenance("test", "status", "value", DateTimeOffset.UtcNow);
        var status = new AffectedPackageStatus(input, provenance);

        Assert.Equal(expected, status.Status);
        Assert.Equal(provenance, status.Provenance);
    }

    [Fact]
    public void Constructor_ThrowsForUnknownStatus()
    {
        var provenance = new AdvisoryProvenance("test", "status", "value", DateTimeOffset.UtcNow);
        Assert.Throws<ArgumentOutOfRangeException>(() => new AffectedPackageStatus("unsupported", provenance));
    }

    [Theory]
    [InlineData("Not Impacted", AffectedPackageStatusCatalog.NotAffected)]
    [InlineData("Resolved", AffectedPackageStatusCatalog.Fixed)]
    [InlineData("Mitigation provided", AffectedPackageStatusCatalog.Mitigated)]
    [InlineData("Out of scope", AffectedPackageStatusCatalog.NotApplicable)]
    public void TryNormalize_ReturnsExpectedValue(string input, string expected)
    {
        Assert.True(AffectedPackageStatusCatalog.TryNormalize(input, out var normalized));
        Assert.Equal(expected, normalized);
    }

    [Fact]
    public void TryNormalize_ReturnsFalseForUnknown()
    {
        Assert.False(AffectedPackageStatusCatalog.TryNormalize("unsupported", out _));
    }

    [Fact]
    public void Allowed_ReturnsCanonicalStatuses()
    {
        var expected = new[]
        {
            AffectedPackageStatusCatalog.KnownAffected,
            AffectedPackageStatusCatalog.KnownNotAffected,
            AffectedPackageStatusCatalog.UnderInvestigation,
            AffectedPackageStatusCatalog.Fixed,
            AffectedPackageStatusCatalog.FirstFixed,
            AffectedPackageStatusCatalog.Mitigated,
            AffectedPackageStatusCatalog.NotApplicable,
            AffectedPackageStatusCatalog.Affected,
            AffectedPackageStatusCatalog.NotAffected,
            AffectedPackageStatusCatalog.Pending,
            AffectedPackageStatusCatalog.Unknown,
        };

        Assert.Equal(expected, AffectedPackageStatusCatalog.Allowed);
    }
}
