using System.Collections.Immutable;
using System.Linq;
using System.Text;
using FluentAssertions;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Excititor.Core;
using StellaOps.Excititor.Formats.OpenVEX;

namespace StellaOps.Excititor.Formats.OpenVEX.Tests;

public sealed class OpenVexNormalizerTests
{
    [Fact]
    public async Task NormalizeAsync_ProducesClaimsForStatements()
    {
        var json = """
        {
          "document": {
            "author": "Acme Security",
            "version": "1",
            "issued": "2025-10-01T00:00:00Z",
            "last_updated": "2025-10-05T00:00:00Z"
          },
          "statements": [
            {
              "id": "statement-1",
              "vulnerability": "CVE-2025-2000",
              "status": "not_affected",
              "justification": "code_not_present",
              "products": [
                {
                  "id": "acme-widget@1.2.3",
                  "name": "Acme Widget",
                  "version": "1.2.3",
                  "purl": "pkg:acme/widget@1.2.3",
                  "cpe": "cpe:/a:acme:widget:1.2.3"
                }
              ],
              "statement": "The vulnerable code was never shipped."
            },
            {
              "id": "statement-2",
              "vulnerability": "CVE-2025-2001",
              "status": "affected",
              "products": [
                "pkg:acme/widget@2.0.0"
              ],
              "remediation": "Upgrade to 2.1.0"
            }
          ]
        }
        """;

        var rawDocument = new VexRawDocument(
            "excititor:openvex",
            VexDocumentFormat.OpenVex,
            new Uri("https://example.com/openvex.json"),
            new DateTimeOffset(2025, 10, 6, 0, 0, 0, TimeSpan.Zero),
            "sha256:dummydigest",
            Encoding.UTF8.GetBytes(json),
            ImmutableDictionary<string, string>.Empty);

        var provider = new VexProvider("excititor:openvex", "OpenVEX Provider", VexProviderKind.Vendor);
        var normalizer = new OpenVexNormalizer(NullLogger<OpenVexNormalizer>.Instance);

        var batch = await normalizer.NormalizeAsync(rawDocument, provider, CancellationToken.None);

        batch.Claims.Should().HaveCount(2);

        var notAffected = batch.Claims.Single(c => c.VulnerabilityId == "CVE-2025-2000");
        notAffected.Status.Should().Be(VexClaimStatus.NotAffected);
        notAffected.Justification.Should().Be(VexJustification.CodeNotPresent);
        notAffected.Product.Key.Should().Be("acme-widget@1.2.3");
        notAffected.Product.Purl.Should().Be("pkg:acme/widget@1.2.3");
        notAffected.Document.Revision.Should().Be("1");
        notAffected.AdditionalMetadata["openvex.document.author"].Should().Be("Acme Security");
        notAffected.AdditionalMetadata["openvex.statement.status"].Should().Be("not_affected");
        notAffected.Detail.Should().Be("The vulnerable code was never shipped.");

        var affected = batch.Claims.Single(c => c.VulnerabilityId == "CVE-2025-2001");
        affected.Status.Should().Be(VexClaimStatus.Affected);
        affected.Justification.Should().BeNull();
        affected.Product.Key.Should().Be("pkg:acme/widget@2.0.0");
        affected.Product.Name.Should().Be("pkg:acme/widget@2.0.0");
        affected.Detail.Should().Be("Upgrade to 2.1.0");
    }
}
