package batch

import "testing"

func TestRunStateConstants(t *testing.T) {
	t.Parallel()

	tests := []struct {
		name string
		got  RunState
		want string
	}{
		{name: "running", got: RunStateRunning, want: "running"},
		{name: "completed", got: RunStateCompleted, want: "completed"},
		{name: "completed with warnings", got: RunStateCompletedWithWarnings, want: "completed_with_warnings"},
		{name: "failed", got: RunStateFailed, want: "failed"},
		{name: "cancelled", got: RunStateCancelled, want: "cancelled"},
	}

	for _, tc := range tests {
		tc := tc
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()
			if string(tc.got) != tc.want {
				t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want)
			}
		})
	}

	if isValidRunState(RunState("unexpected")) {
		t.Fatal("isValidRunState(unexpected) = true, want false")
	}
}

func TestItemStateConstants(t *testing.T) {
	t.Parallel()

	stageTests := []struct {
		name string
		got  ItemStage
		want string
	}{
		{name: "probe", got: ItemStageProbe, want: "probe"},
		{name: "provision", got: ItemStageProvision, want: "provision"},
		{name: "confirm", got: ItemStageConfirm, want: "confirm"},
		{name: "validate", got: ItemStageValidate, want: "validate"},
		{name: "done", got: ItemStageDone, want: "done"},
	}
	for _, tc := range stageTests {
		tc := tc
		t.Run("stage/"+tc.name, func(t *testing.T) {
			t.Parallel()
			if string(tc.got) != tc.want {
				t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want)
			}
		})
	}

	confirmationTests := []struct {
		name string
		got  ConfirmationStatus
		want string
	}{
		{name: "pending", got: ConfirmationPending, want: "pending"},
		{name: "confirmed", got: ConfirmationConfirmed, want: "confirmed"},
		{name: "advisory", got: ConfirmationAdvisory, want: "advisory"},
		{name: "failed", got: ConfirmationFailed, want: "failed"},
	}
	for _, tc := range confirmationTests {
		tc := tc
		t.Run("confirmation/"+tc.name, func(t *testing.T) {
			t.Parallel()
			if string(tc.got) != tc.want {
				t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want)
			}
		})
	}

	accessTests := []struct {
		name string
		got  AccessStatus
		want string
	}{
		{name: "unknown", got: AccessStatusUnknown, want: "unknown"},
		{name: "active", got: AccessStatusActive, want: "active"},
		{name: "degraded", got: AccessStatusDegraded, want: "degraded"},
		{name: "broken", got: AccessStatusBroken, want: "broken"},
	}
	for _, tc := range accessTests {
		tc := tc
		t.Run("access/"+tc.name, func(t *testing.T) {
			t.Parallel()
			if string(tc.got) != tc.want {
				t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want)
			}
		})
	}

	matchedAccountStateTests := []struct {
		name string
		got  MatchedAccountState
		want string
	}{
		{name: "none", got: MatchedAccountStateNone, want: "none"},
		{name: "active", got: MatchedAccountStateActive, want: "active"},
		{name: "disabled", got: MatchedAccountStateDisabled, want: "disabled"},
		{name: "deprecated", got: MatchedAccountStateDeprecated, want: "deprecated"},
		{name: "broken", got: MatchedAccountStateBroken, want: "broken"},
	}
	for _, tc := range matchedAccountStateTests {
		tc := tc
		t.Run("matched-account/"+tc.name, func(t *testing.T) {
			t.Parallel()
			if string(tc.got) != tc.want {
				t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want)
			}
		})
	}

	accountResolutionTests := []struct {
		name string
		got  AccountResolution
		want string
	}{
		{name: "created", got: AccountResolutionCreated, want: "created"},
		{name: "reused", got: AccountResolutionReused, want: "reused"},
		{name: "reactivated", got: AccountResolutionReactivated, want: "reactivated"},
		{name: "replaced", got: AccountResolutionReplaced, want: "replaced"},
	}
	for _, tc := range accountResolutionTests {
		tc := tc
		t.Run("account-resolution/"+tc.name, func(t *testing.T) {
			t.Parallel()
			if string(tc.got) != tc.want {
				t.Fatalf("string(%q) = %q, want %q", tc.name, tc.got, tc.want)
			}
		})
	}

	if isValidItemStage(ItemStage("unexpected")) {
		t.Fatal("isValidItemStage(unexpected) = true, want false")
	}
	if isValidConfirmationStatus(ConfirmationStatus("unexpected")) {
		t.Fatal("isValidConfirmationStatus(unexpected) = true, want false")
	}
	if isValidAccessStatus(AccessStatus("unexpected")) {
		t.Fatal("isValidAccessStatus(unexpected) = true, want false")
	}
	if isValidMatchedAccountState(MatchedAccountState("unexpected")) {
		t.Fatal("isValidMatchedAccountState(unexpected) = true, want false")
	}
	if isValidAccountResolution(AccountResolution("unexpected")) {
		t.Fatal("isValidAccountResolution(unexpected) = true, want false")
	}
}

func isValidRunState(state RunState) bool {
	switch state {
	case RunStateRunning, RunStateCompleted, RunStateCompletedWithWarnings, RunStateFailed, RunStateCancelled:
		return true
	default:
		return false
	}
}

func isValidItemStage(stage ItemStage) bool {
	switch stage {
	case ItemStageProbe, ItemStageProvision, ItemStageConfirm, ItemStageValidate, ItemStageDone:
		return true
	default:
		return false
	}
}

func isValidConfirmationStatus(status ConfirmationStatus) bool {
	switch status {
	case ConfirmationPending, ConfirmationConfirmed, ConfirmationAdvisory, ConfirmationFailed:
		return true
	default:
		return false
	}
}

func isValidAccessStatus(status AccessStatus) bool {
	switch status {
	case AccessStatusUnknown, AccessStatusActive, AccessStatusDegraded, AccessStatusBroken:
		return true
	default:
		return false
	}
}

func isValidMatchedAccountState(state MatchedAccountState) bool {
	switch state {
	case MatchedAccountStateNone, MatchedAccountStateActive, MatchedAccountStateDisabled, MatchedAccountStateDeprecated, MatchedAccountStateBroken:
		return true
	default:
		return false
	}
}

func isValidAccountResolution(resolution AccountResolution) bool {
	switch resolution {
	case AccountResolutionCreated, AccountResolutionReused, AccountResolutionReactivated, AccountResolutionReplaced:
		return true
	default:
		return false
	}
}
