package core

import "testing"

func TestOperationTypeValid(t *testing.T) {
	valid := []OperationType{
		OperationClone,
		OperationFetch,
		OperationCommit,
		OperationPush,
		OperationAgentRun,
	}
	for _, typ := range valid {
		if !typ.Valid() {
			t.Fatalf("operation type %q should be valid", typ)
		}
	}
	if OperationType("unknown").Valid() {
		t.Fatal("unknown operation type should be invalid")
	}
}

func TestOperationStateValidTerminalAndTransitions(t *testing.T) {
	tests := []struct {
		name     string
		from     OperationState
		to       OperationState
		allowed  bool
		terminal bool
	}{
		{name: "queued starts running", from: OperationQueued, to: OperationRunning, allowed: true},
		{name: "queued cancels", from: OperationQueued, to: OperationCancelled, allowed: true},
		{name: "running succeeds", from: OperationRunning, to: OperationSucceeded, allowed: true},
		{name: "running fails", from: OperationRunning, to: OperationFailed, allowed: true},
		{name: "running cancels", from: OperationRunning, to: OperationCancelled, allowed: true},
		{name: "queued cannot succeed directly", from: OperationQueued, to: OperationSucceeded},
		{name: "running cannot go back to queued", from: OperationRunning, to: OperationQueued},
		{name: "succeeded is terminal", from: OperationSucceeded, to: OperationRunning, terminal: true},
		{name: "failed is terminal", from: OperationFailed, to: OperationRunning, terminal: true},
		{name: "cancelled is terminal", from: OperationCancelled, to: OperationRunning, terminal: true},
		{name: "same state is not a transition", from: OperationQueued, to: OperationQueued},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if !tt.from.Valid() {
				t.Fatalf("from state %q should be valid", tt.from)
			}
			if !tt.to.Valid() {
				t.Fatalf("to state %q should be valid", tt.to)
			}
			if got := tt.from.CanTransitionTo(tt.to); got != tt.allowed {
				t.Fatalf("CanTransitionTo: got %v want %v", got, tt.allowed)
			}
			if got := tt.from.Terminal(); got != tt.terminal {
				t.Fatalf("Terminal: got %v want %v", got, tt.terminal)
			}
		})
	}
	if OperationState("unknown").Valid() {
		t.Fatal("unknown operation state should be invalid")
	}
}
