package cluster

import (
	"context"
	"testing"

	. "bou.ke/monkey"
	"github.com/golang/mock/gomock"
	mock_clusterdao "github.com/pingcap/dbaas/central/db/dbutil/cluster/mock"
	"github.com/pingcap/dbaas/central/db/entity"
	"github.com/pingcap/dbaas/central/db/tenant"
	api "github.com/pingcap/dbaas/central/infra-api"
	"github.com/pingcap/dbaas/central/model/util"
	"github.com/pingcap/log"
	. "github.com/smartystreets/goconvey/convey"
	"github.com/tidbcloud/pkgv2/secret/encrypt"
	mock_encrypt "github.com/tidbcloud/pkgv2/secret/encrypt/mock_encryptor"
)

func fakeExecuteSqlCommon(
	ctx context.Context, cluster *entity.Cluster, clause string, api api.InfraFacade,
	enc encrypt.Encryptor, getProxy util.GetProxyFunc, timeout int,
) error {
	return nil
}

func TestSyncReadonly(t *testing.T) {
	Convey("TestSyncReadonly", t, func() {
		ctrl := gomock.NewController(t)
		defer ctrl.Finish()
		logger := log.L()
		ctx := context.Background()
		mockClusterDaoCli := mock_clusterdao.NewMockClusterDaoFacade(ctrl)
		mockEncryptorCli := mock_encrypt.NewMockEncryptor(ctrl)
		model := Model{
			log:       logger,
			encryptor: mockEncryptorCli,
			dao:       mockClusterDaoCli,
		}
		userContext := UserContext{
			Model: model,
			log:   logger,
			tenantAndUser: &tenant.User{
				TenantID: entity.ID(111),
			},
		}

		guard := Patch(util.ExecuteSqlCommon, fakeExecuteSqlCommon)
		defer guard.Unpatch()

		clusterList := []entity.Cluster{
			{
				Updatable: entity.Updatable{
					Base: entity.Base{
						ID: entity.ID(1),
					},
				},
				ProjectID: entity.ID(2),
				Status:    entity.ClusterStatusNormal,
				ReadOnly:  uint64(2),
			},
		}
		clusterWriteable := entity.Cluster{
			Updatable: entity.Updatable{
				Base: entity.Base{
					ID: entity.ID(1),
				},
			},
			ProjectID: entity.ID(2),
			Status:    entity.ClusterStatusNormal,
			ReadOnly:  uint64(0),
		}

		Convey("test force sync and sync from cluster to db", func() {
			mockClusterDaoCli.EXPECT().FindClusters(gomock.Any()).Return(clusterList, nil)
			mockClusterDaoCli.EXPECT().GetCluster(gomock.Any()).Return(clusterList[0], nil)
			mockClusterDaoCli.EXPECT().UpdateCluster(clusterWriteable, gomock.Any(), gomock.Any()).Return(nil)
			err := BgContext(userContext).SyncReadonly(ctx)
			So(err, ShouldBeNil)
		})
	})
}
