using StellaOps.Feedser.Normalization.Identifiers;

namespace StellaOps.Feedser.Normalization.Tests;

public sealed class CpeNormalizerTests
{
    [Fact]
    public void TryNormalizeCpe_Preserves2Dot3Format()
    {
        var input = "cpe:2.3:A:Example:Product:1.0:*:*:*:*:*:*:*";

        var success = IdentifierNormalizer.TryNormalizeCpe(input, out var normalized);

        Assert.True(success);
        Assert.Equal("cpe:2.3:a:example:product:1.0:*:*:*:*:*:*:*", normalized);
    }

    [Fact]
    public void TryNormalizeCpe_UpgradesUriBinding()
    {
        var input = "cpe:/o:RedHat:Enterprise_Linux:8";

        var success = IdentifierNormalizer.TryNormalizeCpe(input, out var normalized);

        Assert.True(success);
        Assert.Equal("cpe:2.3:o:redhat:enterprise_linux:8:*:*:*:*:*:*:*", normalized);
    }

    [Fact]
    public void TryNormalizeCpe_InvalidInputReturnsFalse()
    {
        var success = IdentifierNormalizer.TryNormalizeCpe("not-a-cpe", out var normalized);

        Assert.False(success);
        Assert.Null(normalized);
    }

    [Fact]
    public void TryNormalizeCpe_DecodesPercentEncodingAndEscapes()
    {
        var input = "cpe:/a:Example%20Corp:Widget%2fSuite:1.0:update:%7e:%2a";

        var success = IdentifierNormalizer.TryNormalizeCpe(input, out var normalized);

        Assert.True(success);
        Assert.Equal(@"cpe:2.3:a:example\ corp:widget\/suite:1.0:update:*:*:*:*:*:*", normalized);
    }

    [Fact]
    public void TryNormalizeCpe_ExpandsEditionFields()
    {
        var input = "cpe:/a:Vendor:Product:1.0:update:~pro~~windows~~:en-US";

        var success = IdentifierNormalizer.TryNormalizeCpe(input, out var normalized);

        Assert.True(success);
        Assert.Equal("cpe:2.3:a:vendor:product:1.0:update:*:en-us:pro:*:windows:*", normalized);
    }

    [Fact]
    public void TryNormalizeCpe_PreservesEscapedCharactersIn23()
    {
        var input = @"cpe:2.3:a:example:printer\/:1.2.3:*:*:*:*:*:*:*";

        var success = IdentifierNormalizer.TryNormalizeCpe(input, out var normalized);

        Assert.True(success);
        Assert.Equal(@"cpe:2.3:a:example:printer\/:1.2.3:*:*:*:*:*:*:*", normalized);
    }
}
