package core

import (
	"testing"
)

func TestDagTopoSort(t *testing.T) {
	t.Run("cadena lineal A->B->C produce tres niveles", func(t *testing.T) {
		steps := []DagStep{
			{Name: "a"},
			{Name: "b", Depends: []string{"a"}},
			{Name: "c", Depends: []string{"b"}},
		}
		levels, err := DagTopoSort(steps)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if len(levels) != 3 {
			t.Fatalf("levels: got %d, want 3", len(levels))
		}
		if len(levels[0]) != 1 || levels[0][0].Name != "a" {
			t.Errorf("levels[0]: got %v, want [a]", stepNames(levels[0]))
		}
		if len(levels[1]) != 1 || levels[1][0].Name != "b" {
			t.Errorf("levels[1]: got %v, want [b]", stepNames(levels[1]))
		}
		if len(levels[2]) != 1 || levels[2][0].Name != "c" {
			t.Errorf("levels[2]: got %v, want [c]", stepNames(levels[2]))
		}
	})

	t.Run("diamond A->B A->C B->D C->D produce cuatro niveles", func(t *testing.T) {
		steps := []DagStep{
			{Name: "a"},
			{Name: "b", Depends: []string{"a"}},
			{Name: "c", Depends: []string{"a"}},
			{Name: "d", Depends: []string{"b", "c"}},
		}
		levels, err := DagTopoSort(steps)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		// Expected: level0=[a], level1=[b,c], level2=[d]
		if len(levels) != 3 {
			t.Fatalf("levels: got %d, want 3", len(levels))
		}
		if len(levels[0]) != 1 || levels[0][0].Name != "a" {
			t.Errorf("levels[0]: got %v, want [a]", stepNames(levels[0]))
		}
		if len(levels[1]) != 2 {
			t.Errorf("levels[1]: got %v, want 2 steps", stepNames(levels[1]))
		}
		if len(levels[2]) != 1 || levels[2][0].Name != "d" {
			t.Errorf("levels[2]: got %v, want [d]", stepNames(levels[2]))
		}
	})

	t.Run("steps paralelos sin depends produce un solo nivel", func(t *testing.T) {
		steps := []DagStep{
			{Name: "x"},
			{Name: "y"},
			{Name: "z"},
		}
		levels, err := DagTopoSort(steps)
		if err != nil {
			t.Fatalf("unexpected error: %v", err)
		}
		if len(levels) != 1 {
			t.Fatalf("levels: got %d, want 1", len(levels))
		}
		if len(levels[0]) != 3 {
			t.Errorf("levels[0]: got %d steps, want 3", len(levels[0]))
		}
	})

	t.Run("ciclo A->B->A retorna error", func(t *testing.T) {
		steps := []DagStep{
			{Name: "a", Depends: []string{"b"}},
			{Name: "b", Depends: []string{"a"}},
		}
		_, err := DagTopoSort(steps)
		if err == nil {
			t.Fatal("expected error for cycle, got nil")
		}
	})
}

// stepNames extracts step names for readable test output.
func stepNames(steps []DagStep) []string {
	names := make([]string, len(steps))
	for i, s := range steps {
		names[i] = stepRef(s)
	}
	return names
}
