package dataservice

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/observability/pkg/common/errors"
	"github.com/tidbcloud/observability/pkg/common/structs"
	"github.com/tidbcloud/observability/pkg/resourcemanager"
	"github.com/tidbcloud/observability/test/mockresourcemanager"
	"go.uber.org/mock/gomock"
)

func TestGetHandler(t *testing.T) {
	first := GetHandler()
	assert.Equal(t, historicalDataHandler, first)
	second := GetHandler()
	assert.Equal(t, historicalDataHandler, second)
}

func TestHistoricalDataHandler_GetArchivedCluster(t *testing.T) {
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()

	rw := mockresourcemanager.NewMockArchivedClusterReaderWriter(ctrl)
	resourcemanager.MockArchivedClusterReaderWriter(rw)

	t.Run("cache", func(t *testing.T) {
		k := structs.ClusterUniqueKey{
			BizType:       "cache-b",
			TenantID:      "cache-b",
			ProjectID:     "cache-b",
			ApplicationID: "cache-b",
		}
		historicalClusterCache.SetDefault(k.Splice(), structs.ArchivedClusterInfo{
			VMAccountID: "999",
		})

		cluster, err := GetHandler().GetArchivedCluster(context.TODO(), k)
		assert.NoError(t, err)
		assert.Equal(t, "999", cluster.VMAccountID)
	})

	t.Run("error", func(t *testing.T) {
		rw.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(structs.ArchivedClusterInfo{}, errors.New(errors.UnrecognizedError, "")).Times(1)
		_, err := GetHandler().GetArchivedCluster(context.TODO(), structs.ClusterUniqueKey{})
		assert.Error(t, err)
	})
	t.Run("parallel", func(t *testing.T) {
		rw.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any()).Return(structs.ArchivedClusterInfo{
			VMAccountID: "123123",
		}, nil).AnyTimes()

		time.Sleep(time.Second * 2)
		for i := 0; i < 10; i++ {
			go func() {
				cluster, err := GetHandler().GetArchivedCluster(context.TODO(), structs.ClusterUniqueKey{
					BizType:       "b",
					TenantID:      "t1",
					ProjectID:     "p1",
					ApplicationID: "a1",
				})
				assert.NoError(t, err)
				assert.Equal(t, "123123", cluster.VMAccountID)
			}()
		}

		time.Sleep(time.Second * 2)
	})
}
