package regionalservice

import (
	"context"
	stderrors "errors"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	v1 "github.com/tidbcloud/observability/api/regionalserver/resourceworker/v1"
	"github.com/tidbcloud/observability/pkg/common/constants"
	commonerrors "github.com/tidbcloud/observability/pkg/common/errors"
	"github.com/tidbcloud/observability/pkg/common/message"
	"github.com/tidbcloud/observability/pkg/resourcemanager"
	"github.com/tidbcloud/observability/test/mockresourcemanager"
	"go.uber.org/mock/gomock"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestPauseReconcile(t *testing.T) {
	t.Run("get cluster error", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		clusterRW := mockresourcemanager.NewMockClusterReaderWriter(ctrl)
		resourcemanager.MockClusterReaderWriter(clusterRW)
		expectedErr := commonerrors.New(commonerrors.ClusterNotFound, "")
		clusterRW.EXPECT().GetCluster(gomock.Any(), "missing").Return(nil, expectedErr)

		err := GetHandler().PauseReconcile(context.Background(), message.PauseReconcileReq{ID: "missing"})

		require.Error(t, err)
		assert.Equal(t, commonerrors.ClusterNotFound, err.(commonerrors.Error).Code())
	})

	t.Run("updates cluster annotation", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		clusterRW := mockresourcemanager.NewMockClusterReaderWriter(ctrl)
		resourcemanager.MockClusterReaderWriter(clusterRW)
		cluster := &v1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "test", Namespace: "test"}}
		clusterRW.EXPECT().GetCluster(gomock.Any(), "test").Return(cluster, nil)
		clusterRW.EXPECT().UpdateCluster(gomock.Any(), cluster).Return(nil)

		err := GetHandler().PauseReconcile(context.Background(), message.PauseReconcileReq{
			ID:           "test",
			PauseCluster: true,
		})

		require.NoError(t, err)
		assert.Equal(t, "true", cluster.Annotations[constants.AnnotationKeyPauseReconcile])
	})

	t.Run("returns update error", func(t *testing.T) {
		ctrl := gomock.NewController(t)
		clusterRW := mockresourcemanager.NewMockClusterReaderWriter(ctrl)
		resourcemanager.MockClusterReaderWriter(clusterRW)
		cluster := &v1.Cluster{ObjectMeta: metav1.ObjectMeta{
			Name:      "test",
			Namespace: "test",
			Annotations: map[string]string{
				constants.AnnotationKeyPauseReconcile: "true",
			},
		}}
		expectedErr := stderrors.New("update failed")
		clusterRW.EXPECT().GetCluster(gomock.Any(), "test").Return(cluster, nil)
		clusterRW.EXPECT().UpdateCluster(gomock.Any(), cluster).Return(expectedErr)

		err := GetHandler().PauseReconcile(context.Background(), message.PauseReconcileReq{ID: "test"})

		assert.ErrorIs(t, err, expectedErr)
		assert.Equal(t, "false", cluster.Annotations[constants.AnnotationKeyPauseReconcile])
	})
}
