using Sdt.Config;

namespace Sdt.Runner;

public static class TargetRunner
{
    /// <summary>
    /// Returns the ordered list of real (non-virtual) steps needed to execute <paramref name="target"/>,
    /// respecting DependsOn chains. Each step appears at most once.
    /// </summary>
    public static List<BuildTarget> ResolvePlan(
        BuildTarget target,
        IReadOnlyDictionary<string, BuildTarget> allTargets)
    {
        var visited = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        var plan = new List<BuildTarget>();
        Visit(target, allTargets, visited, plan);
        return plan;
    }

    private static void Visit(
        BuildTarget target,
        IReadOnlyDictionary<string, BuildTarget> allTargets,
        HashSet<string> visited,
        List<BuildTarget> plan)
    {
        if (!visited.Add(target.Id))
            return;

        // Recurse into dependencies first (topological order)
        foreach (var depId in target.DependsOn)
        {
            if (allTargets.TryGetValue(depId, out var dep))
                Visit(dep, allTargets, visited, plan);
        }

        // Virtual aggregator targets (null Command) are just dependency collectors
        if (target.Command is not null)
            plan.Add(target);
    }
}
