using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using StellaOps.Scanner.Sbomer.BuildXPlugin;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Manifest;
using StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.TestUtilities;
using Xunit;

namespace StellaOps.Scanner.Sbomer.BuildXPlugin.Tests.Manifest;

public sealed class BuildxPluginManifestLoaderTests
{
    private static readonly JsonSerializerOptions SerializerOptions = new(JsonSerializerDefaults.Web)
    {
        WriteIndented = true
    };

    [Fact]
    public async Task LoadAsync_ReturnsManifestWithSourceInformation()
    {
        await using var temp = new TempDirectory();
        var manifestPath = System.IO.Path.Combine(temp.Path, "stellaops.manifest.json");
        await File.WriteAllTextAsync(manifestPath, BuildSampleManifestJson("stellaops.sbom-indexer"));

        var loader = new BuildxPluginManifestLoader(temp.Path);
        var manifests = await loader.LoadAsync(CancellationToken.None);

        var manifest = Assert.Single(manifests);
        Assert.Equal("stellaops.sbom-indexer", manifest.Id);
        Assert.Equal("0.1.0", manifest.Version);
        Assert.Equal(manifestPath, manifest.SourcePath);
        Assert.Equal(Path.GetDirectoryName(manifestPath), manifest.SourceDirectory);
    }

    [Fact]
    public async Task LoadDefaultAsync_ThrowsWhenNoManifests()
    {
        await using var temp = new TempDirectory();
        var loader = new BuildxPluginManifestLoader(temp.Path);

        await Assert.ThrowsAsync<BuildxPluginException>(() => loader.LoadDefaultAsync(CancellationToken.None));
    }

    [Fact]
    public async Task LoadAsync_ThrowsWhenRestartRequiredMissing()
    {
        await using var temp = new TempDirectory();
        var manifestPath = Path.Combine(temp.Path, "failure.manifest.json");
        await File.WriteAllTextAsync(manifestPath, BuildSampleManifestJson("stellaops.failure", requiresRestart: false));

        var loader = new BuildxPluginManifestLoader(temp.Path);

        await Assert.ThrowsAsync<BuildxPluginException>(() => loader.LoadAsync(CancellationToken.None));
    }

    private static string BuildSampleManifestJson(string id, bool requiresRestart = true)
    {
        var manifest = new BuildxPluginManifest
        {
            SchemaVersion = BuildxPluginManifest.CurrentSchemaVersion,
            Id = id,
            DisplayName = "Sample",
            Version = "0.1.0",
            RequiresRestart = requiresRestart,
            EntryPoint = new BuildxPluginEntryPoint
            {
                Type = "dotnet",
                Executable = "StellaOps.Scanner.Sbomer.BuildXPlugin.dll"
            },
            Cas = new BuildxPluginCas
            {
                Protocol = "filesystem",
                DefaultRoot = "cas"
            }
        };

        return JsonSerializer.Serialize(manifest, SerializerOptions);
    }
}
