using Sdt.Config;
using Xunit;

namespace DevTool.Tests;

public sealed class WorkflowModelBuilderTests
{
    [Fact]
    public void TargetsOnly_Strict_ThrowsMigrationError()
    {
        var cfg = new DevToolConfig
        {
            Targets =
            [
                new BuildTarget
                {
                    Id = "build",
                    Label = "Build",
                    Command = "dotnet",
                    Args = ["build"],
                }
            ]
        };

        var ex = Assert.Throws<InvalidOperationException>(() => WorkflowModelBuilder.Normalize(cfg, LegacyMode.Strict));
        Assert.Contains("Legacy 'targets' are not allowed in strict mode", ex.Message, StringComparison.OrdinalIgnoreCase);
    }

    [Fact]
    public void TargetsOnly_Compat_ProducesWarningAndConvertedWorkflow()
    {
        var cfg = new DevToolConfig
        {
            Targets =
            [
                new BuildTarget
                {
                    Id = "build",
                    Label = "Build",
                    Command = "dotnet",
                    Args = ["build"],
                }
            ]
        };

        var result = WorkflowModelBuilder.Normalize(cfg, LegacyMode.Compat);

        Assert.Single(result.Workflows);
        Assert.Contains(result.Warnings, w => w.Contains("legacy 'targets'", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void WorkflowsOnly_HasNoLegacyWarning()
    {
        var cfg = new DevToolConfig
        {
            Workflows =
            [
                new WorkflowDefinition
                {
                    Id = "build",
                    Label = "Build",
                    Steps =
                    [
                        new WorkflowStep
                        {
                            Id = "run",
                            Label = "Run",
                            Command = "dotnet",
                            Args = ["build"],
                        }
                    ]
                }
            ]
        };

        var result = WorkflowModelBuilder.Normalize(cfg, LegacyMode.Strict);

        Assert.Single(result.Workflows);
        Assert.DoesNotContain(result.Warnings, w => w.Contains("legacy 'targets'", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void Mixed_PrefersWorkflowsDeterministically()
    {
        var cfg = new DevToolConfig
        {
            Targets =
            [
                new BuildTarget
                {
                    Id = "legacy",
                    Label = "Legacy",
                    Command = "dotnet",
                    Args = ["build"],
                }
            ],
            Workflows =
            [
                new WorkflowDefinition
                {
                    Id = "new",
                    Label = "New",
                    Steps =
                    [
                        new WorkflowStep
                        {
                            Id = "step",
                            Label = "Step",
                            Command = "dotnet",
                            Args = ["build"],
                        }
                    ]
                }
            ]
        };

        var result = WorkflowModelBuilder.Normalize(cfg, LegacyMode.Strict);

        Assert.Single(result.Workflows);
        Assert.Equal("new", result.Workflows[0].Id);
        Assert.Contains(result.Warnings, w => w.Contains("Both 'workflows' and legacy 'targets'", StringComparison.OrdinalIgnoreCase));
    }

    [Fact]
    public void LegacyPwshTarget_InfersToolRequirements_FromScript()
    {
        var cfg = new DevToolConfig
        {
            Targets =
            [
                new BuildTarget
                {
                    Id = "web",
                    Label = "Web",
                    Command = "pwsh",
                    Args = ["-NoProfile", "-File", "scripts/publish-app.ps1", "-Target", "web"],
                }
            ]
        };

        var result = WorkflowModelBuilder.Normalize(cfg, LegacyMode.Compat);
        var step = Assert.Single(result.Workflows).Steps.Single();

        Assert.Contains(step.Requires, r => r.Tool == "python");
        Assert.Contains(step.Requires, r => r.Tool == "node");
        Assert.Contains(step.Requires, r => r.Tool == "npm");
    }
}
