package entity

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
)

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

	tests := []struct {
		name            string
		provider        apiv1.ProviderType
		dataStorage     *apiv1.SharedPool_ObjectStorage
		internalStorage *apiv1.SharedPool_ObjectStorage
		want            string
		wantErr         bool
	}{
		{
			name:     "aws internal storage",
			provider: apiv1.ProviderType_AWS,
			dataStorage: &apiv1.SharedPool_ObjectStorage{
				Bucket: "data-bucket",
				Prefix: "data-prefix",
			},
			internalStorage: &apiv1.SharedPool_ObjectStorage{
				Bucket: "internal-bucket",
				Prefix: "internal-prefix",
			},
			want: "s3://internal-bucket/internal-prefix/global-sort",
		},
		{
			name:     "alicloud canonical oss uri",
			provider: apiv1.ProviderType_ALICLOUD,
			internalStorage: &apiv1.SharedPool_ObjectStorage{
				Bucket: "oss-bucket",
				Prefix: "/prefix",
			},
			want: "oss://oss-bucket/prefix/global-sort",
		},
		{
			name:     "no data storage fallback",
			provider: apiv1.ProviderType_AWS,
			dataStorage: &apiv1.SharedPool_ObjectStorage{
				Bucket: "data-bucket",
			},
			internalStorage: &apiv1.SharedPool_ObjectStorage{},
			wantErr:         true,
		},
		{
			name:     "bucket not ready",
			provider: apiv1.ProviderType_AWS,
			wantErr:  true,
		},
		{
			name:     "unsupported provider",
			provider: apiv1.ProviderType_GCP,
			internalStorage: &apiv1.SharedPool_ObjectStorage{
				Bucket: "bucket",
			},
			wantErr: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()

			sharedPool := &SharedPool{SharedPool: apiv1.SharedPool{
				Provider:        &apiv1.Provider{Type: tt.provider},
				ObjectStorage:   tt.dataStorage,
				InternalStorage: tt.internalStorage,
			}}
			got, err := sharedPool.GetPlanReplayerStorageRoot()
			if tt.wantErr {
				require.Error(t, err)
				return
			}
			require.NoError(t, err)
			assert.Equal(t, tt.want, got)
		})
	}
}
