package execution

import (
	"errors"
	"fmt"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestClassifyErrorTypedRoleOperationFailures(t *testing.T) {
	tests := []struct {
		name    string
		outcome ApplyOutcome
		want    ErrorKind
	}{
		{
			name: "invalid request", outcome: ApplyInvalidRequest,
			want: ErrorInvalidRequest,
		},
		{
			name: "authority denied", outcome: ApplyAuthorityDenied,
			want: ErrorForbidden,
		},
		{
			name: "not found", outcome: ApplyNotFound,
			want: ErrorNotFound,
		},
		{
			name: "version conflict", outcome: ApplyVersionConflict,
			want: ErrorConflict,
		},
		{
			name: "operation conflict", outcome: ApplyOperationConflict,
			want: ErrorConflict,
		},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			kind, ok := ClassifyError(fmt.Errorf(
				"wrapped role operation failure: %w",
				&ApplyError{Outcome: tt.outcome},
			))

			require.True(t, ok)
			require.Equal(t, tt.want, kind)
		})
	}
}

func TestClassifyErrorKeepsUncertainRoleOperationFailuresUnclassified(t *testing.T) {
	tests := []struct {
		name string
		err  error
	}{
		{name: "unknown outcome", err: &ApplyError{Outcome: ApplyOutcome("future_outcome")}},
		{name: "timeout", err: &ApplyError{Outcome: ApplyTimeout}},
		{name: "server error", err: &ApplyError{Outcome: ApplyServerError}},
		{name: "context cancelled", err: &ApplyError{Outcome: ApplyContextCancelled}},
		{name: "response lost", err: &ApplyError{Outcome: ApplyResponseLost}},
		{name: "network", err: errors.New("network down")},
	}

	for _, tt := range tests {
		tt := tt
		t.Run(tt.name, func(t *testing.T) {
			kind, ok := ClassifyError(fmt.Errorf(
				"wrapped uncertain role operation failure: %w", tt.err,
			))

			require.False(t, ok)
			require.Empty(t, kind)
		})
	}
}
