using System.Collections.Immutable;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Vexer.Attestation.Dsse;
using StellaOps.Vexer.Attestation.Models;
using StellaOps.Vexer.Attestation.Signing;
using StellaOps.Vexer.Core;

namespace StellaOps.Vexer.Attestation.Tests;

public sealed class VexDsseBuilderTests
{
    [Fact]
    public async Task CreateEnvelopeAsync_ProducesDeterministicPayload()
    {
        var signer = new FakeSigner("signature-value", "key-1");
        var builder = new VexDsseBuilder(signer, NullLogger<VexDsseBuilder>.Instance);

        var request = new VexAttestationRequest(
            ExportId: "exports/123",
            QuerySignature: new VexQuerySignature("filters"),
            Artifact: new VexContentAddress("sha256", "deadbeef"),
            Format: VexExportFormat.Json,
            CreatedAt: DateTimeOffset.UtcNow,
            SourceProviders: ImmutableArray.Create("vendor"),
            Metadata: ImmutableDictionary<string, string>.Empty);

        var envelope = await builder.CreateEnvelopeAsync(request, request.Metadata, CancellationToken.None);

        Assert.Equal("application/vnd.in-toto+json", envelope.PayloadType);
        Assert.Single(envelope.Signatures);
        Assert.Equal("signature-value", envelope.Signatures[0].Signature);
        Assert.Equal("key-1", envelope.Signatures[0].KeyId);

        var digest = VexDsseBuilder.ComputeEnvelopeDigest(envelope);
        Assert.StartsWith("sha256:", digest);
    }

    private sealed class FakeSigner : IVexSigner
    {
        private readonly string _signature;
        private readonly string _keyId;

        public FakeSigner(string signature, string keyId)
        {
            _signature = signature;
            _keyId = keyId;
        }

        public ValueTask<VexSignedPayload> SignAsync(ReadOnlyMemory<byte> payload, CancellationToken cancellationToken)
            => ValueTask.FromResult(new VexSignedPayload(_signature, _keyId));
    }
}
