using Sdt.Config;
using Sdt.Core;
using Xunit;

namespace DevTool.Tests;

public sealed class PrereqInstallerServiceTests
{
    [Fact]
    public async Task PreferredInstallCommands_AreUsedFirst()
    {
        var svc = new PrereqInstallerService();
        var cfg = new DevToolConfig
        {
            Tooling = new ToolingConfig
            {
                Tools =
                [
                    new ToolInstallDefinition
                    {
                        Tool = "dotnet",
                        PreferredInstallCommands =
                        [
                            "echo install dotnet",
                            "dotnet --info"
                        ]
                    }
                ]
            }
        };

        var plan = await svc.GetInstallPlanAsync("dotnet", Directory.GetCurrentDirectory(), cfg);

        Assert.True(plan.Supported);
        Assert.Equal("dotnet", plan.Tool);
        Assert.Equal(2, plan.Commands.Count);
        Assert.Equal("echo", plan.Commands[0].Command);
        Assert.Equal("dotnet", plan.Commands[1].Command);
    }

    [Fact]
    public async Task DiagInstallPlanFailure_FallsBackToTemplatePlan()
    {
        var root = Path.Combine(Path.GetTempPath(), "sdt-prereq-" + Guid.NewGuid().ToString("N"));
        var scripts = Path.Combine(root, "scripts");
        Directory.CreateDirectory(scripts);
        await File.WriteAllTextAsync(Path.Combine(scripts, "diag.py"), "import sys\nsys.exit(2)\n");

        var svc = new PrereqInstallerService();
        var plan = await svc.GetInstallPlanAsync("npm", root, new DevToolConfig());

        Assert.True(plan.Supported);
        Assert.NotEmpty(plan.Commands);
        Assert.Contains("fallback", plan.Summary, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public async Task DiagInstallPlanInvalidJson_FallsBackToTemplatePlan()
    {
        var root = Path.Combine(Path.GetTempPath(), "sdt-prereq-" + Guid.NewGuid().ToString("N"));
        var scripts = Path.Combine(root, "scripts");
        Directory.CreateDirectory(scripts);
        await File.WriteAllTextAsync(Path.Combine(scripts, "diag.py"), "print('not-json')\n");

        var svc = new PrereqInstallerService();
        var plan = await svc.GetInstallPlanAsync("dotnet", root, new DevToolConfig());

        Assert.True(plan.Supported);
        Assert.NotEmpty(plan.Commands);
        Assert.Contains("fallback", plan.Summary, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public async Task TauriFallbackPlan_IsMultiStepAndClear()
    {
        var root = Path.Combine(Path.GetTempPath(), "sdt-prereq-" + Guid.NewGuid().ToString("N"));
        Directory.CreateDirectory(root);

        var svc = new PrereqInstallerService();
        var plan = await svc.GetInstallPlanAsync("tauri", root, new DevToolConfig());

        Assert.True(plan.Supported);
        Assert.True(plan.Commands.Count >= 3);
        Assert.Contains("tauri", plan.Summary, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public async Task TauriFallbackPlan_IncludesRustAndCliCommands()
    {
        var root = Path.Combine(Path.GetTempPath(), "sdt-prereq-" + Guid.NewGuid().ToString("N"));
        Directory.CreateDirectory(root);

        var svc = new PrereqInstallerService();
        var plan = await svc.GetInstallPlanAsync("tauri", root, new DevToolConfig());

        Assert.Contains(plan.Commands, c => c.Args.Any(a => a.Contains("rustup", StringComparison.OrdinalIgnoreCase)));
        Assert.Contains(plan.Commands, c => c.Args.Any(a => a.Contains("@tauri-apps/cli", StringComparison.OrdinalIgnoreCase)));
    }
}
