package controlplane

import (
	"testing"
)

func TestValidateTransition(t *testing.T) {
	tests := []struct {
		name    string
		from    Phase
		to      Phase
		wantErr bool
	}{
		// Valid transitions
		{"created -> preview_pending", PhaseCreated, PhasePreviewPending, false},
		{"created -> canceled", PhaseCreated, PhaseCanceled, false},
		{"preview_pending -> preview_running", PhasePreviewPending, PhasePreviewRunning, false},
		{"preview_running -> preview_succeeded", PhasePreviewRunning, PhasePreviewSucceeded, false},
		{"preview_running -> preview_failed", PhasePreviewRunning, PhasePreviewFailed, false},
		{"preview_failed -> preview_pending (re-preview)", PhasePreviewFailed, PhasePreviewPending, false},
		{"preview_succeeded -> approving", PhasePreviewSucceeded, PhaseApproving, false},
		{"approving -> apply_pending", PhaseApproving, PhaseApplyPending, false},
		{"apply_pending -> apply_running", PhaseApplyPending, PhaseApplyRunning, false},
		{"apply_running -> apply_succeeded", PhaseApplyRunning, PhaseApplySucceeded, false},
		{"apply_running -> apply_failed", PhaseApplyRunning, PhaseApplyFailed, false},
		{"apply_failed -> apply_pending (retry)", PhaseApplyFailed, PhaseApplyPending, false},
		{"apply_running -> canceled", PhaseApplyRunning, PhaseCanceled, false},

		// Invalid transitions
		{"created -> apply_pending (skip preview)", PhaseCreated, PhaseApplyPending, true},
		{"created -> approving (skip preview)", PhaseCreated, PhaseApproving, true},
		{"preview_succeeded -> apply_pending (skip approval)", PhasePreviewSucceeded, PhaseApplyPending, true},
		{"apply_succeeded -> anything (terminal)", PhaseApplySucceeded, PhaseCreated, true},
		{"canceled -> anything (terminal)", PhaseCanceled, PhaseCreated, true},
		{"apply_succeeded -> canceled (already terminal)", PhaseApplySucceeded, PhaseCanceled, true},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidateTransition(tt.from, tt.to)
			if (err != nil) != tt.wantErr {
				t.Errorf("ValidateTransition(%q, %q) error = %v, wantErr %v", tt.from, tt.to, err, tt.wantErr)
			}
		})
	}
}

func TestPhaseIsTerminal(t *testing.T) {
	tests := []struct {
		phase    Phase
		terminal bool
	}{
		{PhaseCreated, false},
		{PhasePreviewPending, false},
		{PhaseApplyRunning, false},
		{PhaseApplyFailed, false},
		{PhaseApplySucceeded, true},
		{PhaseCanceled, true},
	}

	for _, tt := range tests {
		t.Run(string(tt.phase), func(t *testing.T) {
			if got := tt.phase.IsTerminal(); got != tt.terminal {
				t.Errorf("Phase(%q).IsTerminal() = %v, want %v", tt.phase, got, tt.terminal)
			}
		})
	}
}
