package lobby

import "testing"

// TestNextStatusFromSnapshot covers the pure status-mapping function
// that drives `OnRuntimeSnapshot`'s lifecycle transitions. The Phase
// 25 contribution is the `running → paused` branch on
// `engine_unreachable` / `generation_failed`: the order handler relies
// on the `paused` game status to reject late submits with
// `turn_already_closed`.
func TestNextStatusFromSnapshot(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name          string
		currentStatus string
		runtimeStatus string
		wantStatus    string
		wantTransit   bool
	}{
		{
			name:          "starting then running flips to running",
			currentStatus: GameStatusStarting,
			runtimeStatus: "running",
			wantStatus:    GameStatusRunning,
			wantTransit:   true,
		},
		{
			name:          "running on running snapshot does not transit",
			currentStatus: GameStatusRunning,
			runtimeStatus: "running",
			wantStatus:    GameStatusRunning,
			wantTransit:   false,
		},
		{
			name:          "starting then engine_unreachable flips to start_failed",
			currentStatus: GameStatusStarting,
			runtimeStatus: "engine_unreachable",
			wantStatus:    GameStatusStartFailed,
			wantTransit:   true,
		},
		{
			name:          "starting then generation_failed flips to start_failed",
			currentStatus: GameStatusStarting,
			runtimeStatus: "generation_failed",
			wantStatus:    GameStatusStartFailed,
			wantTransit:   true,
		},
		{
			name:          "running then engine_unreachable flips to paused",
			currentStatus: GameStatusRunning,
			runtimeStatus: "engine_unreachable",
			wantStatus:    GameStatusPaused,
			wantTransit:   true,
		},
		{
			name:          "running then generation_failed flips to paused",
			currentStatus: GameStatusRunning,
			runtimeStatus: "generation_failed",
			wantStatus:    GameStatusPaused,
			wantTransit:   true,
		},
		{
			name:          "paused stays paused on repeated failed snapshot",
			currentStatus: GameStatusPaused,
			runtimeStatus: "generation_failed",
			wantStatus:    GameStatusPaused,
			wantTransit:   false,
		},
		{
			name:          "starting then start_failed flips to start_failed",
			currentStatus: GameStatusStarting,
			runtimeStatus: "start_failed",
			wantStatus:    GameStatusStartFailed,
			wantTransit:   true,
		},
		{
			name:          "running ignores start_failed",
			currentStatus: GameStatusRunning,
			runtimeStatus: "start_failed",
			wantStatus:    GameStatusRunning,
			wantTransit:   false,
		},
		{
			name:          "running on finished flips to finished",
			currentStatus: GameStatusRunning,
			runtimeStatus: "finished",
			wantStatus:    GameStatusFinished,
			wantTransit:   true,
		},
		{
			name:          "finished stays finished on finished snapshot",
			currentStatus: GameStatusFinished,
			runtimeStatus: "finished",
			wantStatus:    GameStatusFinished,
			wantTransit:   false,
		},
		{
			name:          "cancelled stays cancelled on finished snapshot",
			currentStatus: GameStatusCancelled,
			runtimeStatus: "finished",
			wantStatus:    GameStatusCancelled,
			wantTransit:   false,
		},
		{
			name:          "paused on stopped snapshot flips to finished",
			currentStatus: GameStatusPaused,
			runtimeStatus: "stopped",
			wantStatus:    GameStatusFinished,
			wantTransit:   true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			got, transit := nextStatusFromSnapshot(tt.currentStatus, RuntimeSnapshot{
				RuntimeStatus: tt.runtimeStatus,
			})
			if got != tt.wantStatus {
				t.Errorf("status = %q, want %q", got, tt.wantStatus)
			}
			if transit != tt.wantTransit {
				t.Errorf("transit = %v, want %v", transit, tt.wantTransit)
			}
		})
	}
}
