package impl

import (
	"context"
	"testing"

	"github.com/AlekSi/pointer"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/suite"
	ticdc_v1 "github.com/tidbcloud/cluster-service-ng/api/tidbcloud/ticdc-service/v1"
	config_manager_mock "github.com/tidbcloud/dataflow-service-ng/app/models/config_manager/mock"
	"github.com/tidbcloud/dataflow-service-ng/app/models/domain"
	ticdc_spec_mock "github.com/tidbcloud/dataflow-service-ng/app/models/ticdc_spec/mock"
	"github.com/tidbcloud/dataflow-service-ng/app/repo/entity"
	repo_mock "github.com/tidbcloud/dataflow-service-ng/app/repo/mock"
	grpcli_mock "github.com/tidbcloud/dataflow-service-ng/pkg/grpc/grpcli/mock"
	regionalapi "github.com/tidbcloud/dataflow-service-ng/pkg/regional-api"
	regionalapi_mock "github.com/tidbcloud/dataflow-service-ng/pkg/regional-api/mock"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/pkgv2/db/mock_db"
	"go.uber.org/mock/gomock"
	"gorm.io/gorm"
)

type clusterModelRegionalImplTestSuite struct {
	suite.Suite

	mockInstanceTypeModel      *ticdc_spec_mock.CDCInstanceTypeModel
	mockTiCDCClusterCli        *regionalapi_mock.TiCDCClusterClient
	mockTiCDCClusterRepo       *repo_mock.TiCDCClusterRepo
	mockTiCDCCustomStorageRepo *repo_mock.TiCDCCustomStorageRepo
	mockConfigManager          *config_manager_mock.TiCDCClusterConfigManager
	mockRegionCli              *grpcli_mock.RegionGrpcClient

	model *clusterModelRegionalImpl
}

func (s *clusterModelRegionalImplTestSuite) SetupSuite() {
	s.mockInstanceTypeModel = ticdc_spec_mock.NewCDCInstanceTypeModel(s.T())
	s.mockTiCDCClusterCli = regionalapi_mock.NewTiCDCClusterClient(s.T())
	s.mockTiCDCClusterRepo = repo_mock.NewTiCDCClusterRepo(s.T())
	s.mockTiCDCCustomStorageRepo = repo_mock.NewTiCDCCustomStorageRepo(s.T())
	s.mockConfigManager = config_manager_mock.NewTiCDCClusterConfigManager(s.T())
	s.mockRegionCli = grpcli_mock.NewRegionGrpcClient(s.T())
	s.model = &clusterModelRegionalImpl{
		instanceTypeModel:      s.mockInstanceTypeModel,
		ticdcClusterCli:        s.mockTiCDCClusterCli,
		ticdcClusterRepo:       s.mockTiCDCClusterRepo,
		ticdcCustomStorageRepo: s.mockTiCDCCustomStorageRepo,
		configManager:          s.mockConfigManager,
		regionCli:              s.mockRegionCli,
	}
}

func (s *clusterModelRegionalImplTestSuite) TestConvertRegionalTiCDCClusterConfig() {
	testcases := []struct {
		configData   *domain.TiCDCConfigData
		expectedConf *ticdc_v1.TiCDCCluster_Configuration
	}{
		{
			configData: &domain.TiCDCConfigData{
				BaseImage: nil,
				Tag:       nil,
				Config:    nil,
			},
			expectedConf: &ticdc_v1.TiCDCCluster_Configuration{
				BaseImage: "",
				Tag:       "",
				Config:    "",
			},
		},
		{
			configData: &domain.TiCDCConfigData{
				BaseImage: nil,
				Tag:       nil,
				Config:    map[string]interface{}{},
			},
			expectedConf: &ticdc_v1.TiCDCCluster_Configuration{
				BaseImage: "",
				Tag:       "",
				Config:    "",
			},
		},
		{
			configData: &domain.TiCDCConfigData{
				BaseImage: nil,
				Tag:       nil,
				Config: map[string]interface{}{
					"a": 123,
					"b": "abc",
				},
			},
			expectedConf: &ticdc_v1.TiCDCCluster_Configuration{
				BaseImage: "",
				Tag:       "",
				Config:    "a = 123\nb = 'abc'\n",
			},
		},
		{
			configData: &domain.TiCDCConfigData{
				BaseImage: pointer.ToString("ticdc"),
				Tag:       nil,
				Config: map[string]interface{}{
					"a": 123,
					"b": "abc",
				},
			},
			expectedConf: &ticdc_v1.TiCDCCluster_Configuration{
				BaseImage: "ticdc",
				Tag:       "",
				Config:    "a = 123\nb = 'abc'\n",
			},
		},
		{
			configData: &domain.TiCDCConfigData{
				BaseImage: pointer.ToString("ticdc"),
				Tag:       pointer.ToString("v7.5.0"),
				Config: map[string]interface{}{
					"a": 123,
					"b": "abc",
				},
			},
			expectedConf: &ticdc_v1.TiCDCCluster_Configuration{
				BaseImage: "ticdc",
				Tag:       "v7.5.0",
				Config:    "a = 123\nb = 'abc'\n",
			},
		},
	}

	for _, tc := range testcases {
		conf, err := s.model.convertRegionalTiCDCClusterConfig(tc.configData)
		s.NoError(err)
		s.Equal(tc.expectedConf, conf)
	}
}

func (s *clusterModelRegionalImplTestSuite) TestConvertRegionalTiCDCCluster() {
	ticdcClusterEnt := &entity.TiCDCCluster{
		Updatable: entity.Updatable{
			Base: entity.Base{
				ID: 1111,
			},
		},
		SharedPoolID:      "111",
		Name:              "cdc-111",
		Version:           "v7.5.0",
		Region:            "us-west-2",
		CloudProvider:     entity.CloudProviderTypeAWS,
		SpecificationCode: "32rcu",
		Status:            entity.TiCDCClusterStatusCreating,
	}
	configData := &domain.TiCDCConfigData{
		BaseImage: pointer.ToString("ticdc"),
		Tag:       pointer.ToString("v7.5.0"),
		Config: map[string]interface{}{
			"a": 123,
			"b": "abc",
		},
	}
	instanceType := &domain.CDCInstanceType{
		Name:             "32rcu",
		RCUNum:           32,
		StorageType:      "gp3",
		Replicas:         2,
		MachineCPUNum:    16,
		MachineMemoryGi:  64,
		MachineStorageGi: 1000,
		Iops:             3000,
		ThroughputMbs:    300,
	}

	expectedRegionalTiCDCCluster := &ticdc_v1.TiCDCCluster{
		Id:           "cdc-111",
		SharedPoolId: "111",
		NodeSpec: &ticdc_v1.NodeInfo{
			Count:             2,
			CpuCore:           16,
			MemoryGi:          64,
			KubernetesVersion: "",
		},
		Storage: &ticdc_v1.TiCDCCluster_Storage{
			Type:          "gp3",
			SizeGi:        1000,
			Iops:          3000,
			ThroughputMbs: 300,
		},
		Configuration: &ticdc_v1.TiCDCCluster_Configuration{
			BaseImage: "ticdc",
			Tag:       "v7.5.0",
			Config:    "a = 123\nb = 'abc'\n",
		},
	}

	regionalTiCDCCluster, err := s.model.convertRegionalTiCDCCluster(ticdcClusterEnt, configData, instanceType)
	s.NoError(err)
	s.Equal(expectedRegionalTiCDCCluster, regionalTiCDCCluster)
}

func (s *clusterModelRegionalImplTestSuite) TestCreateRegionalTiCDCCluster() {
	ticdcClusterEnt := &entity.TiCDCCluster{
		SharedPoolID: "111",
		Name:         "cdc-111",
		Region:       "us-west-2",
	}
	configData := &domain.TiCDCConfigData{}
	instanceType := &domain.CDCInstanceType{}

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("CreateTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		err := s.model.createRegionalTiCDCClusterIgnoreExists(
			context.Background(), ticdcClusterEnt, configData, instanceType)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	s.Run("ticdc cluster exists", func() {
		mockErr := bizerr.New(bizerr.ErrCodeRecordExist, "ticdc cluster already exists")
		call := s.mockTiCDCClusterCli.
			On("CreateTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		err := s.model.createRegionalTiCDCClusterIgnoreExists(
			context.Background(), ticdcClusterEnt, configData, instanceType)
		s.NoError(err)
	})

	s.Run("call regional successfully", func() {
		regionMatcher := mock.MatchedBy(func(region *regionalapi.Region) bool {
			return region.SharedPoolID == "111"
		})
		reqMatcher := mock.MatchedBy(func(req *ticdc_v1.CreateTiCDCClusterRequest) bool {
			return req.TicdcClusterId == "cdc-111"
		})
		call := s.mockTiCDCClusterCli.
			On("CreateTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(nil, nil)
		defer call.Unset()
		err := s.model.createRegionalTiCDCClusterIgnoreExists(
			context.Background(), ticdcClusterEnt, configData, instanceType)
		s.NoError(err)
		s.mockTiCDCClusterCli.AssertCalled(
			s.T(), "CreateTiCDCCluster", mock.Anything, regionMatcher, reqMatcher)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestCreateReq2Entity() {
	req := &domain.CreateTiCDCClusterReq{
		TenantID:          1,
		SharedPoolID:      "111",
		CloudProvider:     entity.CloudProviderTypeAWS,
		Name:              "cdc-111",
		Region:            "us-west-2",
		Version:           "v7.5.0",
		SpecificationCode: "32rcu",
	}
	expectedTiCDCClusterEnt := &entity.TiCDCCluster{
		SharedPoolID:      "111",
		Name:              "cdc-111",
		CloudProvider:     entity.CloudProviderTypeAWS,
		Region:            "us-west-2",
		Version:           "v7.5.0",
		SpecificationCode: "32rcu",
		Status:            entity.TiCDCClusterStatusCreating,
	}

	ticdcClusterEnt := s.model.createReq2Entity(req)
	s.Equal(expectedTiCDCClusterEnt, ticdcClusterEnt)
}

func (s *clusterModelRegionalImplTestSuite) TestDoCreate() {
	ticdcClusterEnt := &entity.TiCDCCluster{
		SharedPoolID:      "111",
		Name:              "cdc-111",
		CloudProvider:     entity.CloudProviderTypeAWS,
		Region:            "us-west-2",
		Version:           "v7.5.0",
		SpecificationCode: "32rcu",
		Status:            entity.TiCDCClusterStatusCreating,
	}
	s.Run("save entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(mockErr)
		defer call.Unset()
		err := s.model.doCreate(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "save ticdc cluster entity")
	})

	saveCall := s.mockTiCDCClusterRepo.
		On("Save", mock.Anything, mock.Anything).
		Return(nil).
		Run(func(args mock.Arguments) {
			cluster := args[1].(*entity.TiCDCCluster)
			cluster.ID = 1111
		})
	defer saveCall.Unset()

	s.Run("create config error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockConfigManager.On("Create", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		err := s.model.doCreate(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "create ticdc cluster configuration")
	})

	createConfCall := s.mockConfigManager.
		On("Create", mock.Anything, &domain.CreateTiCDCClusterConfigReq{
			TiCDCClusterID:     1111,
			TiDBClusterVersion: "v7.5.0",
			CloudProvider:      "aws",
		}).Return(nil, nil)
	defer createConfCall.Unset()

	s.Run("get config error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockConfigManager.On("Get", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		err := s.model.doCreate(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "get ticdc cluster configuration")
	})

	getConfCall := s.mockConfigManager.
		On("Get", mock.Anything, &domain.GetTiCDCClusterConfigReq{
			TiCDCClusterID: 1111,
		}).Return(&domain.GetTiCDCClusterConfigResp{Configuration: &domain.TiCDCConfigData{}}, nil)
	defer getConfCall.Unset()

	s.Run("cal cdc instance type error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "cal ticdc instance type")
		call := s.mockInstanceTypeModel.
			On("CalCDCInstanceType", mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		err := s.model.doCreate(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "cal ticdc instance type")
	})

	getInsTypeCall := s.mockInstanceTypeModel.
		On("CalCDCInstanceType", mock.Anything, &domain.CalCDCInstanceTypeReq{
			ExpectedSpecification: "32rcu",
			CloudProvider:         entity.CloudProviderTypeAWS,
			Region:                "us-west-2",
		}).Return(&domain.CalCDCInstanceTypeResp{InstanceType: &domain.CDCInstanceType{}}, nil)
	defer getInsTypeCall.Unset()

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("CreateTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		err := s.model.doCreate(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "create regional ticdc cluster")
	})

	regionalCall := s.mockTiCDCClusterCli.
		On("CreateTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
		Return(nil, nil)
	defer regionalCall.Unset()
	s.Run("do create successfully", func() {
		err := s.model.doCreate(context.Background(), ticdcClusterEnt)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestCreate() {
	req := &domain.CreateTiCDCClusterReq{
		CloudProvider:     entity.CloudProviderTypeAWS,
		TenantID:          1,
		SharedPoolID:      "111",
		Name:              "cdc-111",
		Region:            "us-west-2",
		Version:           "v7.5.0",
		SpecificationCode: "32rcu",
	}
	s.Run("get entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Get", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Create(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "get ticdc cluster entity")
	})

	s.Run("existing ticdc cluster is deleting", func() {
		mockEnt := &entity.TiCDCCluster{
			Status: entity.TiCDCClusterStatusDeleting,
		}
		mockEnt.ID = 1111
		call := s.mockTiCDCClusterRepo.On("Get", mock.Anything, mock.Anything).Return(mockEnt, nil)
		defer call.Unset()
		_, err := s.model.Create(context.Background(), req)
		s.Error(err)
		s.Contains(err.Error(), "is deleting")
	})

	s.Run("ticdc cluster exists", func() {
		mockEnt := &entity.TiCDCCluster{}
		mockEnt.ID = 1111
		call := s.mockTiCDCClusterRepo.On("Get", mock.Anything, mock.Anything).Return(mockEnt, nil)
		defer call.Unset()
		resp, err := s.model.Create(context.Background(), req)
		s.NoError(err)
		s.Equal(mockEnt.ID.Uint64(), resp.ID)
	})

	mockGetErr := bizerr.New(bizerr.ErrCodeRecordNotFound, "not found")
	getCall := s.mockTiCDCClusterRepo.On("Get", mock.Anything, mock.Anything).Return(nil, mockGetErr)
	defer getCall.Unset()

	s.Run("transaction error", func() {
		ctrl := gomock.NewController(s.T())
		defer s.cleanTransProvider()
		mockTransProvider := s.newTransProvider(ctrl)
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(mockErr)
		_, err := s.model.Create(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(nil)

	s.Run("create successfully", func() {
		_, err := s.model.Create(context.Background(), req)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) newTransProvider(ctrl *gomock.Controller) *mock_db.MockTransProvider {
	mockTransProvider := mock_db.NewMockTransProvider(ctrl)
	s.model.transProvider = mockTransProvider
	return mockTransProvider
}

func (s *clusterModelRegionalImplTestSuite) cleanTransProvider() {
	s.model.transProvider = nil
}

func (s *clusterModelRegionalImplTestSuite) TestScaleRegionalTiCDCCluster() {
	ticdcClusterEnt := &entity.TiCDCCluster{
		Name:          "cdc-111",
		SharedPoolID:  "111",
		Region:        "us-west-2",
		CloudProvider: entity.CloudProviderTypeAWS,
	}
	instanceType := &domain.CDCInstanceType{
		Replicas:         2,
		StorageType:      "gp3",
		MachineCPUNum:    16,
		MachineMemoryGi:  64,
		MachineStorageGi: 1000,
		Iops:             4000,
		ThroughputMbs:    400,
	}

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("ScaleTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(mockErr)
		defer call.Unset()
		err := s.model.scaleRegionalTiCDCCluster(context.Background(), ticdcClusterEnt, instanceType)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	s.Run("call regional successfully", func() {
		expectedRegion := &regionalapi.Region{
			SharedPoolID: "111",
		}
		expectedScaleReq := &ticdc_v1.ScaleTiCDCClusterRequest{
			TicdcClusterId: "cdc-111",
			NodeSpec: &ticdc_v1.NodeInfo{
				Count:             2,
				CpuCore:           16,
				MemoryGi:          64,
				KubernetesVersion: "",
			},
			Storage: &ticdc_v1.TiCDCCluster_Storage{
				Type:          "gp3",
				SizeGi:        1000,
				Iops:          4000,
				ThroughputMbs: 400,
			},
		}
		call := s.mockTiCDCClusterCli.
			On("ScaleTiCDCCluster", mock.Anything, expectedRegion, expectedScaleReq).
			Return(nil)
		defer call.Unset()
		err := s.model.scaleRegionalTiCDCCluster(context.Background(), ticdcClusterEnt, instanceType)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestDoScale() {
	req := &domain.ScaleTiCDCClusterReq{
		ID:                1111,
		SpecificationCode: "16rcu",
	}
	ticdcClusterEnt := &entity.TiCDCCluster{}
	instanceType := &domain.CDCInstanceType{}

	s.Run("save entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(mockErr)
		defer call.Unset()
		err := s.model.doScale(context.Background(), req, ticdcClusterEnt, instanceType)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "save ticdc cluster entity")
	})

	saveCall := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(nil)
	defer saveCall.Unset()

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("ScaleTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(mockErr)
		defer call.Unset()
		err := s.model.doScale(context.Background(), req, ticdcClusterEnt, instanceType)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	regionalCall := s.mockTiCDCClusterCli.
		On("ScaleTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
		Return(nil)
	defer regionalCall.Unset()

	s.Run("do scale successfully", func() {
		err := s.model.doScale(context.Background(), req, ticdcClusterEnt, instanceType)
		s.NoError(err)
		s.Equal("16rcu", ticdcClusterEnt.SpecificationCode)
		s.Equal(entity.TiCDCClusterStatusScaling, ticdcClusterEnt.Status)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestScale() {
	req := &domain.ScaleTiCDCClusterReq{
		ID:                1111,
		SpecificationCode: "16rcu",
	}

	s.Run("load entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Scale(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "load ticdc cluster entity")
	})

	mockEntity := &entity.TiCDCCluster{
		CloudProvider: entity.CloudProviderTypeAWS,
		Region:        "us-west-2",
	}
	loadCall := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(mockEntity, nil)
	defer loadCall.Unset()

	s.Run("cal instance type error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "cal ticdc instance type")
		call := s.mockInstanceTypeModel.
			On("CalCDCInstanceType", mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Scale(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "cal ticdc instance type")
	})

	getInsTypeCall := s.mockInstanceTypeModel.
		On("CalCDCInstanceType", mock.Anything, &domain.CalCDCInstanceTypeReq{
			ExpectedSpecification: "16rcu",
			CloudProvider:         entity.CloudProviderTypeAWS,
			Region:                "us-west-2",
		}).Return(&domain.CalCDCInstanceTypeResp{}, nil)
	defer getInsTypeCall.Unset()

	s.Run("load custom storage error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "load custom storage error")
		call := s.mockTiCDCCustomStorageRepo.
			On("LoadByTiCDCClusterID", mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Scale(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "load custom storage error")
	})

	loadCustomStorageCall := s.mockTiCDCCustomStorageRepo.
		On("LoadByTiCDCClusterID", mock.Anything, mock.Anything).
		Return(nil, bizerr.WrapGormError(gorm.ErrRecordNotFound, "ticdc custom storage not found"))
	defer loadCustomStorageCall.Unset()

	s.Run("transaction error", func() {
		ctrl := gomock.NewController(s.T())
		defer s.cleanTransProvider()
		mockTransProvider := s.newTransProvider(ctrl)
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(mockErr)
		_, err := s.model.Scale(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(nil)

	s.Run("scale successfully", func() {
		_, err := s.model.Scale(context.Background(), req)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestScaleWithCustomStorage() {
	req := &domain.ScaleTiCDCClusterReq{
		ID:                1111,
		SpecificationCode: "16rcu",
	}

	mockEntity := &entity.TiCDCCluster{
		CloudProvider: entity.CloudProviderTypeAWS,
		Region:        "us-west-2",
		Name:          "cdc-111",
		SharedPoolID:  "111",
	}
	mockEntity.ID = 1111
	s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(mockEntity, nil).Once()

	s.mockInstanceTypeModel.
		On("CalCDCInstanceType", mock.Anything, &domain.CalCDCInstanceTypeReq{
			ExpectedSpecification: "16rcu",
			CloudProvider:         entity.CloudProviderTypeAWS,
			Region:                "us-west-2",
		}).Return(&domain.CalCDCInstanceTypeResp{
		InstanceType: &domain.CDCInstanceType{
			MachineCPUNum:    4,
			MachineMemoryGi:  8,
			Replicas:         1,
			StorageType:      "gp3",
			MachineStorageGi: 100,
			Iops:             1000,
			ThroughputMbs:    100,
		},
	}, nil).Once()

	customStorage := &entity.TiCDCCustomStorage{
		SizeGi:        500,
		Iops:          5000,
		ThroughputMbs: 500,
	}
	s.mockTiCDCCustomStorageRepo.
		On("LoadByTiCDCClusterID", mock.Anything, mock.Anything).
		Return(customStorage, nil).Once()

	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, fc func(context.Context) error) error {
		return fc(ctx)
	})

	s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(nil).Once()

	expectedRegion := &regionalapi.Region{
		SharedPoolID: "111",
	}
	s.mockTiCDCClusterCli.On("ScaleTiCDCCluster", mock.Anything, expectedRegion, mock.MatchedBy(func(req *ticdc_v1.ScaleTiCDCClusterRequest) bool {
		return req.Storage.SizeGi == 500 && req.Storage.Iops == 5000 && req.Storage.ThroughputMbs == 500
	})).Return(nil).Once()

	_, err := s.model.Scale(context.Background(), req)
	s.NoError(err)
}

func (s *clusterModelRegionalImplTestSuite) TestQuery() {
	req := &domain.QueryTiCDCClusterReq{
		ID: 1111,
	}
	s.Run("get entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Get", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Query(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "get ticdc cluster entity")
	})

	mockEntity := &entity.TiCDCCluster{}
	mockEntity.ID = 1111
	loadCall := s.mockTiCDCClusterRepo.On("Get", mock.Anything, mock.Anything).Return(mockEntity, nil)
	defer loadCall.Unset()

	s.Run("query successfully", func() {
		resp, err := s.model.Query(context.Background(), req)
		s.NoError(err)
		s.Equal(mockEntity, resp.TiCDCClusterEntity)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestDeleteRegionalTiCDCCluster() {
	ticdcClusterEnt := &entity.TiCDCCluster{
		Name:          "cdc-111",
		SharedPoolID:  "111",
		Region:        "us-west-2",
		CloudProvider: entity.CloudProviderTypeAWS,
	}

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("DeleteTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(mockErr)
		defer call.Unset()
		err := s.model.deleteRegionalTiCDCCluster(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	s.Run("call regional successfully", func() {
		expectedRegion := &regionalapi.Region{
			SharedPoolID: "111",
		}
		expectedScaleReq := &ticdc_v1.DeleteTiCDCClusterRequest{
			TicdcClusterId: "cdc-111",
		}
		call := s.mockTiCDCClusterCli.
			On("DeleteTiCDCCluster", mock.Anything, expectedRegion, expectedScaleReq).
			Return(nil)
		defer call.Unset()
		err := s.model.deleteRegionalTiCDCCluster(context.Background(), ticdcClusterEnt)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestDoDelete() {
	ticdcClusterEnt := &entity.TiCDCCluster{}
	ticdcClusterEnt.ID = 1111

	s.Run("save entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(mockErr)
		defer call.Unset()
		err := s.model.doDelete(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "save ticdc cluster entity")
	})

	saveCall := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(nil)
	defer saveCall.Unset()

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("DeleteTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
			Return(mockErr)
		defer call.Unset()
		err := s.model.doDelete(context.Background(), ticdcClusterEnt)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	regionalCall := s.mockTiCDCClusterCli.
		On("DeleteTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
		Return(nil)
	defer regionalCall.Unset()

	s.Run("do delete successfully", func() {
		err := s.model.doDelete(context.Background(), ticdcClusterEnt)
		s.NoError(err)
		s.Equal(entity.TiCDCClusterStatusDeleting, ticdcClusterEnt.Status)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestDelete() {
	req := &domain.DeleteTiCDCClusterReq{
		ID: 1111,
	}
	s.Run("load entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Delete(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "load ticdc cluster entity")
	})

	s.Run("ticdc cluster not exists", func() {
		mockErr := bizerr.New(bizerr.ErrCodeRecordNotFound, "not found")
		call := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.Delete(context.Background(), req)
		s.NoError(err)
	})

	mockEnt := &entity.TiCDCCluster{}
	mockEnt.ID = 1111
	loadCall := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(mockEnt, nil)
	defer loadCall.Unset()

	s.Run("ticdc cluster is deleting", func() {
		mockEnt.Status = entity.TiCDCClusterStatusDeleting
		_, err := s.model.Delete(context.Background(), req)
		s.NoError(err)
	})

	s.Run("ticdc cluster is deleted", func() {
		mockEnt.Status = entity.TiCDCClusterStatusDeleted
		_, err := s.model.Delete(context.Background(), req)
		s.NoError(err)
	})

	mockEnt.Status = entity.TiCDCClusterStatusRunning
	s.Run("transaction error", func() {
		ctrl := gomock.NewController(s.T())
		defer s.cleanTransProvider()
		mockTransProvider := s.newTransProvider(ctrl)
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(mockErr)
		_, err := s.model.Delete(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(nil)

	s.Run("delete successfully", func() {
		_, err := s.model.Delete(context.Background(), req)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestUpdateConfigRegionalTiCDCCluster() {
	ticdcClusterEnt := &entity.TiCDCCluster{
		Name:          "cdc-111",
		SharedPoolID:  "111",
		Region:        "us-west-2",
		CloudProvider: entity.CloudProviderTypeAWS,
	}
	configData := &domain.TiCDCConfigData{
		BaseImage: pointer.ToString("ticdc"),
		Tag:       pointer.ToString("v7.5.0"),
		Config: map[string]interface{}{
			"a": 123,
			"b": "abc",
		},
	}

	s.Run("update ticdc cluster entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(mockErr)
		defer call.Unset()
		err := s.model.updateConfigRegionalTiCDCCluster(context.Background(), ticdcClusterEnt, configData)
		s.Error(err)
		s.Contains(err.Error(), "save ticdc cluster entity")
	})

	saveCall := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(nil)
	defer saveCall.Unset()

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("UpdateTiCDCClusterConfig", mock.Anything, mock.Anything, mock.Anything).
			Return(mockErr)
		defer call.Unset()
		err := s.model.updateConfigRegionalTiCDCCluster(context.Background(), ticdcClusterEnt, configData)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	s.Run("call regional successfully", func() {
		expectedRegion := &regionalapi.Region{
			SharedPoolID: "111",
		}
		expectedUpdateReq := &ticdc_v1.UpdateTiCDCClusterConfigRequest{
			TicdcClusterId: "cdc-111",
			Configuration: &ticdc_v1.TiCDCCluster_Configuration{
				BaseImage: "ticdc",
				Tag:       "v7.5.0",
				Config:    "a = 123\nb = 'abc'\n",
			},
		}
		call := s.mockTiCDCClusterCli.
			On("UpdateTiCDCClusterConfig", mock.Anything, expectedRegion, expectedUpdateReq).
			Return(nil)
		defer call.Unset()
		err := s.model.updateConfigRegionalTiCDCCluster(context.Background(), ticdcClusterEnt, configData)
		s.NoError(err)
		s.Equal(entity.TiCDCClusterStatusUpgrading, ticdcClusterEnt.Status)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestApplyConfig() {
	req := &domain.ApplyTiCDCClusterConfigReq{
		TiCDCClusterID: 1111,
	}
	s.Run("load entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		err := s.model.ApplyConfig(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "load ticdc cluster entity")
	})

	mockEntity := &entity.TiCDCCluster{}
	mockEntity.ID = 1111
	loadCall := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(mockEntity, nil)
	defer loadCall.Unset()

	s.Run("get config error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockConfigManager.On("Get", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		err := s.model.ApplyConfig(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "get ticdc cluster configuration")
	})

	getConfCall := s.mockConfigManager.
		On("Get", mock.Anything, &domain.GetTiCDCClusterConfigReq{
			TiCDCClusterID: 1111,
		}).Return(&domain.GetTiCDCClusterConfigResp{Configuration: &domain.TiCDCConfigData{}}, nil)
	defer getConfCall.Unset()

	s.Run("transaction error", func() {
		ctrl := gomock.NewController(s.T())
		defer s.cleanTransProvider()
		mockTransProvider := s.newTransProvider(ctrl)
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(mockErr)
		err := s.model.ApplyConfig(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(nil)

	s.Run("apply config successfully", func() {
		err := s.model.ApplyConfig(context.Background(), req)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestList() {
	req := &domain.ListTiCDCClustersReq{
		SharedPoolID: "111",
	}
	s.Run("list ticdc clusters error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("List", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		_, err := s.model.List(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "list ticdc clusters")
	})

	mockEntities := []entity.TiCDCCluster{
		{
			Name:         "ticdc-1",
			SharedPoolID: "1111",
		},
		{
			Name:         "ticdc-2",
			SharedPoolID: "1111",
		},
	}
	loadCall := s.mockTiCDCClusterRepo.On("List", mock.Anything, mock.Anything).Return(mockEntities, nil)
	defer loadCall.Unset()

	s.Run("list ticdc clusters successfully", func() {
		resp, err := s.model.List(context.Background(), req)
		s.NoError(err)
		s.Equal(mockEntities, resp.Items)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestScale_WithCustomStorage() {
	req := &domain.ScaleTiCDCClusterReq{
		ID:                1111,
		SpecificationCode: "16rcu",
	}

	// Mocks setup
	mockEntity := &entity.TiCDCCluster{
		CloudProvider: "aws",
		Region:        "us-west-2",
		Name:          "cdc-111",
		SharedPoolID:  "111",
	}
	loadCall := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(mockEntity, nil)
	defer loadCall.Unset()

	getInstanceTypeCall := s.mockInstanceTypeModel.
		On("CalCDCInstanceType", mock.Anything, mock.Anything).
		Return(&domain.CalCDCInstanceTypeResp{
			InstanceType: &domain.CDCInstanceType{
				MachineCPUNum:    2,
				MachineMemoryGi:  8,
				Replicas:         2,
				StorageType:      "gp3",
				MachineStorageGi: 100,
				Iops:             3000,
				ThroughputMbs:    300,
			},
		}, nil)
	defer getInstanceTypeCall.Unset()

	customStorage := &entity.TiCDCCustomStorage{
		SizeGi:        2000,
		Iops:          8000,
		ThroughputMbs: 800,
	}
	loadCustomStorageCall := s.mockTiCDCCustomStorageRepo.
		On("LoadByTiCDCClusterID", mock.Anything, mock.Anything).
		Return(customStorage, nil)
	defer loadCustomStorageCall.Unset()

	// Mock Transaction to execute the closure
	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, fc func(context.Context) error) error {
		return fc(ctx)
	})

	// Mock Save in doScale
	saveCall := s.mockTiCDCClusterRepo.On("Save", mock.Anything, mock.Anything).Return(nil)
	defer saveCall.Unset()

	// Mock ScaleTiCDCCluster and verify arguments
	scaleCall := s.mockTiCDCClusterCli.
		On("ScaleTiCDCCluster", mock.Anything, mock.Anything, mock.Anything).
		Run(func(args mock.Arguments) {
			req := args.Get(2).(*ticdc_v1.ScaleTiCDCClusterRequest)
			s.Equal(uint32(2000), req.Storage.SizeGi)
			s.Equal(uint32(8000), req.Storage.Iops)
			s.Equal(uint32(800), req.Storage.ThroughputMbs)
		}).
		Return(nil)
	defer scaleCall.Unset()

	_, err := s.model.Scale(context.Background(), req)
	s.NoError(err)
}

func (s *clusterModelRegionalImplTestSuite) TestUpdateStorage() {
	req := &domain.UpdateTiCDCClusterStorageReq{
		TiCDCClusterID: 1111,
		SizeGi:         100,
		Iops:           3000,
		ThroughputMbs:  300,
	}

	s.Run("load entity error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(nil, mockErr)
		defer call.Unset()
		err := s.model.UpdateStorage(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "load ticdc cluster entity")
	})

	mockEntity := &entity.TiCDCCluster{
		CloudProvider: entity.CloudProviderTypeAWS,
		Region:        "us-west-2",
	}
	mockEntity.ID = 1111
	loadCall := s.mockTiCDCClusterRepo.On("Load", mock.Anything, mock.Anything).Return(mockEntity, nil)
	defer loadCall.Unset()

	s.Run("cal instance type error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "cal ticdc instance type")
		call := s.mockInstanceTypeModel.
			On("CalCDCInstanceType", mock.Anything, mock.Anything).
			Return(nil, mockErr)
		defer call.Unset()
		err := s.model.UpdateStorage(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "get ticdc instance type")
	})

	getInsTypeCall := s.mockInstanceTypeModel.
		On("CalCDCInstanceType", mock.Anything, &domain.CalCDCInstanceTypeReq{
			ExpectedSpecification: mockEntity.SpecificationCode,
			CloudProvider:         entity.CloudProviderTypeAWS,
			Region:                "us-west-2",
		}).Return(&domain.CalCDCInstanceTypeResp{InstanceType: &domain.CDCInstanceType{}}, nil)
	defer getInsTypeCall.Unset()

	s.Run("transaction error", func() {
		ctrl := gomock.NewController(s.T())
		defer s.cleanTransProvider()
		mockTransProvider := s.newTransProvider(ctrl)
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(mockErr)
		err := s.model.UpdateStorage(context.Background(), req)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	ctrl := gomock.NewController(s.T())
	defer s.cleanTransProvider()
	mockTransProvider := s.newTransProvider(ctrl)
	mockTransProvider.EXPECT().Transaction(gomock.Any(), gomock.Any()).Return(nil)

	s.Run("update storage successfully", func() {
		err := s.model.UpdateStorage(context.Background(), req)
		s.NoError(err)
	})
}

func (s *clusterModelRegionalImplTestSuite) TestDoUpdateStorage() {
	req := &domain.UpdateTiCDCClusterStorageReq{
		TiCDCClusterID: 1111,
		SizeGi:         100,
		Iops:           3000,
		ThroughputMbs:  300,
	}
	ticdcClusterEnt := &entity.TiCDCCluster{
		Name:          "cdc-111",
		SharedPoolID:  "111",
		Region:        "us-west-2",
		CloudProvider: entity.CloudProviderTypeAWS,
	}
	ticdcClusterEnt.ID = 1111
	instanceTypeResp := &domain.CalCDCInstanceTypeResp{
		InstanceType: &domain.CDCInstanceType{
			StorageType: "gp3",
		},
	}

	s.Run("save custom storage error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeDB, "network error")
		call := s.mockTiCDCCustomStorageRepo.On("Save", mock.Anything, mock.Anything).Return(mockErr)
		defer call.Unset()
		err := s.model.updateStorage(context.Background(), req, ticdcClusterEnt, instanceTypeResp)
		s.Error(err)
		s.Equal(mockErr.RawErrCode(), err.RawErrCode())
		s.Contains(err.Error(), "save ticdc custom storage entity")
	})

	saveCall := s.mockTiCDCCustomStorageRepo.On("Save", mock.Anything, mock.Anything).Return(nil)
	defer saveCall.Unset()

	s.Run("call regional error", func() {
		mockErr := bizerr.New(bizerr.ErrCodeUnknown, "network error")
		call := s.mockTiCDCClusterCli.
			On("UpdateTiCDCClusterStorage", mock.Anything, mock.Anything, mock.Anything).
			Return(mockErr)
		defer call.Unset()
		err := s.model.updateStorage(context.Background(), req, ticdcClusterEnt, instanceTypeResp)
		s.Error(err)
		s.Equal(mockErr, err)
	})

	s.Run("call regional successfully", func() {
		expectedRegion := &regionalapi.Region{
			SharedPoolID: "111",
		}
		expectedUpdateReq := &ticdc_v1.UpdateTiCDCClusterStorageRequest{
			TicdcClusterId: "cdc-111",
			Storage: &ticdc_v1.TiCDCCluster_Storage{
				Type:          "gp3",
				SizeGi:        100,
				Iops:          3000,
				ThroughputMbs: 300,
			},
		}
		call := s.mockTiCDCClusterCli.
			On("UpdateTiCDCClusterStorage", mock.Anything, expectedRegion, expectedUpdateReq).
			Return(nil)
		defer call.Unset()
		err := s.model.updateStorage(context.Background(), req, ticdcClusterEnt, instanceTypeResp)
		s.NoError(err)
	})
}

func TestClusterModelRegionalImplTestSuite(t *testing.T) {
	suite.Run(t, new(clusterModelRegionalImplTestSuite))
}
