package sdlc

import "testing"

func TestAddTask(t *testing.T) {
	tasks := AddTask(nil, "Create user model")
	tasks = AddTask(tasks, "Add validation")

	if len(tasks) != 2 {
		t.Fatalf("len = %d, want 2", len(tasks))
	}
	if tasks[0].ID != "task-001" {
		t.Errorf("tasks[0].ID = %q, want task-001", tasks[0].ID)
	}
	if tasks[1].ID != "task-002" {
		t.Errorf("tasks[1].ID = %q, want task-002", tasks[1].ID)
	}
	if tasks[0].Status != TaskPending {
		t.Errorf("tasks[0].Status = %q, want pending", tasks[0].Status)
	}
}

func TestStartTask(t *testing.T) {
	tasks := AddTask(nil, "Task 1")

	tasks, err := StartTask(tasks, "task-001")
	if err != nil {
		t.Fatalf("StartTask: %v", err)
	}
	if tasks[0].Status != TaskInProgress {
		t.Errorf("Status = %q, want in_progress", tasks[0].Status)
	}
	if tasks[0].StartedAt == nil {
		t.Error("StartedAt is nil")
	}
}

func TestStartTaskNotFound(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	_, err := StartTask(tasks, "task-999")
	if err != ErrTaskNotFound {
		t.Errorf("err = %v, want ErrTaskNotFound", err)
	}
}

func TestStartTaskWrongStatus(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	tasks, _ = StartTask(tasks, "task-001")
	tasks, _ = CompleteTask(tasks, "task-001")

	_, err := StartTask(tasks, "task-001")
	if err == nil {
		t.Error("StartTask on complete task should fail")
	}
}

func TestCompleteTask(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	tasks, _ = StartTask(tasks, "task-001")

	tasks, err := CompleteTask(tasks, "task-001")
	if err != nil {
		t.Fatalf("CompleteTask: %v", err)
	}
	if tasks[0].Status != TaskComplete {
		t.Errorf("Status = %q, want complete", tasks[0].Status)
	}
	if tasks[0].DoneAt == nil {
		t.Error("DoneAt is nil")
	}
}

func TestCompleteTaskWrongStatus(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	_, err := CompleteTask(tasks, "task-001")
	if err == nil {
		t.Error("CompleteTask on pending task should fail")
	}
}

func TestBlockTask(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	tasks, err := BlockTask(tasks, "task-001")
	if err != nil {
		t.Fatalf("BlockTask: %v", err)
	}
	if tasks[0].Status != TaskBlocked {
		t.Errorf("Status = %q, want blocked", tasks[0].Status)
	}
}

func TestPendingTasks(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	tasks = AddTask(tasks, "Task 2")
	tasks = AddTask(tasks, "Task 3")
	tasks, _ = StartTask(tasks, "task-001")
	tasks, _ = CompleteTask(tasks, "task-001")

	pending := PendingTasks(tasks)
	if len(pending) != 2 {
		t.Errorf("PendingTasks len = %d, want 2", len(pending))
	}
}

func TestNextTask(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	tasks = AddTask(tasks, "Task 2")
	tasks, _ = StartTask(tasks, "task-001")
	tasks, _ = CompleteTask(tasks, "task-001")

	next := NextTask(tasks)
	if next == nil {
		t.Fatal("NextTask = nil, want task-002")
	}
	if next.ID != "task-002" {
		t.Errorf("NextTask.ID = %q, want task-002", next.ID)
	}
}

func TestAllTasksComplete(t *testing.T) {
	if AllTasksComplete(nil) {
		t.Error("AllTasksComplete(nil) = true, want false")
	}

	tasks := AddTask(nil, "Task 1")
	tasks = AddTask(tasks, "Task 2")

	if AllTasksComplete(tasks) {
		t.Error("AllTasksComplete = true with pending tasks")
	}

	tasks, _ = StartTask(tasks, "task-001")
	tasks, _ = CompleteTask(tasks, "task-001")
	tasks, _ = StartTask(tasks, "task-002")
	tasks, _ = CompleteTask(tasks, "task-002")

	if !AllTasksComplete(tasks) {
		t.Error("AllTasksComplete = false with all complete")
	}
}

func TestSummarizeTasks(t *testing.T) {
	tasks := AddTask(nil, "Task 1")
	tasks = AddTask(tasks, "Task 2")
	tasks = AddTask(tasks, "Task 3")
	tasks, _ = StartTask(tasks, "task-001")
	tasks, _ = CompleteTask(tasks, "task-001")
	tasks, _ = StartTask(tasks, "task-002")

	s := SummarizeTasks(tasks)
	if s.Total != 3 {
		t.Errorf("Total = %d, want 3", s.Total)
	}
	if s.Completed != 1 {
		t.Errorf("Completed = %d, want 1", s.Completed)
	}
	if s.InProgress != 1 {
		t.Errorf("InProgress = %d, want 1", s.InProgress)
	}
	if s.Pending != 1 {
		t.Errorf("Pending = %d, want 1", s.Pending)
	}
}
