package app

import (
	"fmt"

	coreapi "github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	tidbclouddb "github.com/tidbcloud/pkgv2/db"
	tidbcloudtiinf "github.com/tidbcloud/tiinf/tiinf"
	"google.golang.org/grpc"

	bffclusterv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/bff/cluster_management/v1beta1"
	bffv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/bff/cluster_management/v1beta2"
	openapidedicatedv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/dedicated/v1beta1"
	openapifsv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/fs/v1beta2"
	openapingv1beta2 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/nextgen/v1beta2"
	openapiserverlessv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/serverless/v1beta1"
	openapizerov1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/zero/v1beta1"
	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/bff/cluster"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/bff/orchestrator"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/bff/tidbxinstance"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/bff/tidbxregion"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/core"
	internalbackup "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/backup"
	internalcapacitytemplate "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/capacitytemplate"
	internalcluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/cluster"
	internalcmek "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/cmek"
	internalcompat "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/compat"
	internalstatus "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/customstatus"
	internaldatasync "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/datasynchronization"
	internaldedicatedtopremiumprecheck "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/dedicatedtopremiumprecheck"
	internalexport "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/export"
	internalfsregion "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/fsregion"
	internalmaintenance "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/maintenance"
	internalmigrationcluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/migrationcluster"
	internalorgconfig "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/orgconfig"
	internalprivatelinkservicemigration "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/privatelinkservicemigration"
	internalrcuquota "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/rcuquota"
	internalregion "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/region"
	internalresourcepool "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/resourcepool"
	internalshadowpool "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/shadowpool"
	internalspu "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/spu"
	internalvpc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/vpc"
	internalvpcpeering "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/internalapi/vpcpeering"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/auditlog"
	dedicatedappcluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/cluster"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/cmek"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/maintenance"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/privatelink"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/region"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/tidbgroup"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/dedicated/vpc"
	fsappregion "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/fs/region"
	nextgendappauditlog "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/auditlog"
	nextgendappbackup "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/backup"
	nextgendappbyocvpcpeering "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/byocvpcpeering"
	nextgencmek "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/cmek"
	nextgendappexport "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/export"
	nextgendapplogredactionpolicy "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/logredactionpolicy"
	nextgendappplanreplayer "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/planreplayer"
	nextgendappprivateendpoint "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/privateendpoint"
	nextgendapppublicconnectionsetting "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/publicconnectionsetting"
	nextgendappquota "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/quota"
	nextgendappregion "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/region"
	nextgendappresourcepool "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/resourcepool"
	nextgendapptidb "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/nextgen/tidb"
	serverlessapp "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/serverless"
	serverlessclusterapi "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/serverless/cluster"
	zeroopenapi "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/zero"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/proxy"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/account"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/repository"
	customstatussvc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/customstatus"
	datasynchronizationsvc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/datasynchronization"
	dedicatedcluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/dedicated/cluster"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/dedicated/migrationcluster"
	dedicatedtopremiumprechecksvc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/dedicatedtopremiumprecheck"
	maintenancewindowsvcsvc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/maintenancewindow"
	nextgencluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/nextgen/cluster"
	serverlesscluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/serverless/cluster"
	serverlessuser "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/serverless/user"
	shadowpoolmgmtsvc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/shadowpool"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/worker"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/worker/shadowpool"
	workflowsvc "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/workflow"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/billingcli"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/dataflowcli"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/eventbus/auditlogsender"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/globaldedicatedcli"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/globalnextgencli"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/globalserverlesscli"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/remoteencryptor"
	infrarepo "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/infra/repository"
	permissionmw "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/authorization/permission"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/authorization/permission/checker"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/config"
	"github.com/tidbcloud/tidb-management-service/utilities/clusterevent"
	featgatesvc "github.com/tidbcloud/tidb-management-service/utilities/featuregate"
	"github.com/tidbcloud/tidb-management-service/utilities/lease"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

func init() {
	// Register shadow pool metrics
	shadowpool.RegisterMetrics()
	internalshadowpool.RegisterMetrics()
	zeroopenapi.RegisterMetrics()
	serverlessclusterapi.RegisterMetrics()
	tidbxinstance.RegisterMetrics()
}

func RegisterGrpcServer(
	f tidbcloudtiinf.TiInf,
	cfg *config.Config,
	dbProvider tidbclouddb.TransProvider,
	wflow workflow.Workflow,
	accountCli account.Client,
	clusterRepo repository.ClusterRepository,
	resourceTagRepo repository.ResourceTagRepository,
	clusterTagBindingRepo repository.ClusterTagBindingRepository,
	customStatusRepo repository.CustomStatusRepository,
	lockRepo repository.LockRepo,
	maintenanceWindowRepo repository.MaintenanceWindowRepo,
	maintenanceTaskRepo repository.MaintenanceTaskRepo,
	maintenanceTaskExecutionRepo repository.MaintenanceTaskExecutionRepo,
	migrationClusterRepo repository.MigrationClusterRepo,
	dataSyncRepo repository.DataSynchronizationRepo,
	shadowPoolRepo repository.ShadowPoolRepository,
	zeroRentRecordRepo repository.ZeroRentRecordRepository,
	projectMigrationTaskRepo repository.ProjectMigrationTaskRepo,
	dedicatedToPremiumPrecheckRepo repository.DedicatedToPremiumPrecheckRepo,
) error {
	serverlessCli, err := globalserverlesscli.NewClient(cfg.Serverless)
	if err != nil {
		return fmt.Errorf("init serverless global failed: %w", err)
	}
	dedicatedCli, err := globaldedicatedcli.NewClient(cfg.Dedicated)
	if err != nil {
		return fmt.Errorf("init dedicated global failed: %w", err)
	}
	dataflowCli, err := dataflowcli.NewClient(cfg.DataFlow)
	if err != nil {
		return fmt.Errorf("init dataflow failed: %w", err)
	}
	nextgenCli, err := globalnextgencli.NewClient(cfg.NextGen)
	if err != nil {
		return fmt.Errorf("init nextgen global failed: %w", err)
	}
	billingCli := billingcli.NewBillingClient(cfg)

	encryptor := remoteencryptor.NewEncryptor(cfg.AwsSecret.CMKArn)

	auditLogSender := auditlogsender.NewConsoleAuditLogSender()
	clusterEventCommitter := clusterevent.NewWALCommitter(dbProvider)

	featCli := featgatesvc.NewFeatureGate(cfg.FeatureGates, nil)

	orgRuConfigRepo := infrarepo.NewOrganizationRuConfigRepo(dbProvider)

	// init domain services (created before RegisterDags so they can be passed to workflow actions)
	serverlessClusterSvc, err := serverlesscluster.NewService(
		clusterRepo,
		resourceTagRepo,
		clusterTagBindingRepo,
		zeroRentRecordRepo,
		customStatusRepo,
		lockRepo,
		shadowPoolRepo,
		serverlessCli,
		accountCli,
		billingCli,
		&cfg.BizConfig,
		dbProvider,
		encryptor,
		wflow,
		orgRuConfigRepo,
		clusterEventCommitter,
	)
	if err != nil {
		return err
	}

	if err := workflowsvc.RegisterDags(
		wflow,
		dbProvider,
		customStatusRepo,
		migrationClusterRepo,
		clusterRepo,
		dataSyncRepo,
		projectMigrationTaskRepo,
		dedicatedToPremiumPrecheckRepo,
		serverlessCli,
		serverlessClusterSvc,
		accountCli,
		encryptor,
		dedicatedCli,
		dataflowCli,
		nextgenCli,
		clusterEventCommitter,
		workflowsvc.DedicatedToPremiumPrecheckOptions{
			SupportedChangefeedSinkTypes: supportedChangefeedSinkTypes(cfg.DedicatedToPremiumPrecheck),
		},
	); err != nil {
		return fmt.Errorf("register workflow dags failed: %w", err)
	}

	serverlessUserSvc := serverlessuser.NewService(
		clusterRepo,
		customStatusRepo,
		serverlessCli,
		dbProvider,
	)
	dedicatedClusterSvc, err := dedicatedcluster.NewService(
		clusterRepo,
		resourceTagRepo,
		clusterTagBindingRepo,
		customStatusRepo,
		dedicatedCli,
		dataflowCli,
		accountCli,
		encryptor,
		dbProvider,
		wflow,
		maintenanceTaskExecutionRepo,
	)
	if err != nil {
		return err
	}
	customStatusSvc := customstatussvc.NewService(
		clusterRepo,
		customStatusRepo,
		dedicatedCli,
		serverlessCli,
		nextgenCli,
		dbProvider,
	)
	maintenanceWindowSvc := maintenancewindowsvcsvc.NewService(
		clusterRepo,
		maintenanceWindowRepo,
		maintenanceTaskRepo,
		maintenanceTaskExecutionRepo,
		customStatusRepo,
		accountCli,
		dbProvider,
		clusterEventCommitter,
		wflow,
		serverlessClusterSvc,
		dedicatedClusterSvc,
		mustNewLeaseLocker(dbProvider),
	)
	migrationClusterSvc := migrationcluster.NewService(
		migrationClusterRepo,
		clusterRepo,
		dedicatedCli,
		dbProvider,
		wflow,
	)
	dataSyncSvc := datasynchronizationsvc.NewService(
		dataSyncRepo,
		clusterRepo,
		dedicatedCli,
		dataflowCli,
		encryptor,
		dbProvider,
		wflow,
	)
	dedicatedToPremiumPrecheckSvc := dedicatedtopremiumprechecksvc.NewService(
		dbProvider, dedicatedToPremiumPrecheckRepo, clusterRepo, accountCli, dedicatedCli, wflow,
	)

	nextgenSvc, err := nextgencluster.NewService(
		clusterRepo,
		resourceTagRepo,
		clusterTagBindingRepo,
		customStatusRepo,
		nextgenCli,
		accountCli,
		dbProvider,
		encryptor,
		wflow,
		orgRuConfigRepo,
		clusterEventCommitter,
	)
	if err != nil {
		return err
	}

	// init dedicated server
	dedicatedRegionServer := region.NewServer(dedicatedCli, accountCli)
	dedicatedClusterServer := dedicatedappcluster.NewServer(
		dedicatedClusterSvc,
		customStatusSvc,
		dedicatedCli,
		auditLogSender,
		dedicatedRegionServer,
		accountCli,
		cfg.OneConsole,
	)
	dedicatedVpcServer := vpc.NewServer(dedicatedCli, dedicatedClusterSvc, customStatusRepo, auditLogSender)
	dedicatedMaintenanceServer := maintenance.NewServer(maintenanceWindowSvc, auditLogSender)
	dedicatedTidbGroupServer := tidbgroup.NewServer(dedicatedCli, dedicatedClusterSvc, customStatusRepo, auditLogSender)
	dedicatedPrivateLinkServer := privatelink.NewServer(
		dedicatedCli,
		dedicatedClusterSvc,
		customStatusRepo,
		auditLogSender,
	)
	dedicatedAuditLogServer := auditlog.NewServer(dedicatedClusterSvc, dedicatedCli, auditLogSender)
	dedicatedCmekServer := cmek.NewServer(dedicatedCli, auditLogSender)

	// init nextgen server
	restoreFromPremiumAdapter := nextgendapptidb.NewRestoreFromPremiumAdapter(nextgenSvc, nextgenCli, accountCli)
	restoreFromDedicatedAdapter := nextgendapptidb.NewRestoreFromDedicatedAdapter(dataflowCli)
	restoreFromClassicAdapter := nextgendapptidb.NewRestoreFromClassicAdapter(nextgenCli)
	nextgenClusterServer := nextgendapptidb.NewServer(
		nextgenSvc,
		customStatusSvc,
		auditLogSender,
		nextgenCli,
		accountCli,
		dbProvider,
		restoreFromPremiumAdapter,
		restoreFromDedicatedAdapter,
		restoreFromClassicAdapter,
		dataflowCli,
		cfg.RootPasswordKMS,
		cfg.OneConsole,
	)

	nextgenBackupServer := nextgendappbackup.NewServer(
		nextgenCli,
		nextgenSvc,
		accountCli,
		auditLogSender,
	)

	nextgenExportServer := nextgendappexport.NewServer(nextgenCli, nextgenSvc, auditLogSender)

	nextgenPublicConnectionSettingServer := nextgendapppublicconnectionsetting.NewServer(
		nextgenCli,
		auditLogSender,
	)

	nextgenByocVpcPeeringServer := nextgendappbyocvpcpeering.NewServer(nextgenCli, auditLogSender)
	nextgenPlanReplayerServer := nextgendappplanreplayer.NewServer(nextgenCli, auditLogSender)

	nextgenPrivateEndpointConnectionServer := nextgendappprivateendpoint.NewServer(
		nextgenCli,
		customStatusRepo,
		auditLogSender,
	)

	nextgenRegionServer := nextgendappregion.NewServer(nextgenCli, accountCli, customStatusSvc)

	nextgenResourcePoolServer := nextgendappresourcepool.NewServer(nextgenCli, auditLogSender)

	nextgenQuotaServer := nextgendappquota.NewServer(nextgenCli)

	nextgenAuditLogServer := nextgendappauditlog.NewServer(nextgenSvc, nextgenCli, auditLogSender)

	nextgenLogRedactionPolicyServer := nextgendapplogredactionpolicy.NewServer(nextgenCli, auditLogSender)

	nextgenCmekServer := nextgencmek.NewServer(nextgenCli)

	// init fs server
	fsRegionServer := fsappregion.NewServer(infrarepo.NewFsRegionRepo(dbProvider))

	// init serverless server
	serverlessV1beta1Service := serverlessapp.NewServer(
		serverlessCli,
		serverlessClusterSvc,
		clusterRepo,
		serverlessUserSvc,
		customStatusSvc,
		shadowPoolRepo,
		accountCli,
		auditLogSender,
		cfg.OneConsole,
	)

	// init zero server
	zeroV1beta1Service := zeroopenapi.NewServer(serverlessClusterSvc, shadowPoolRepo, cfg.ShadowPool)

	// init internalapi server
	internalClusterServer := internalcluster.NewServer(
		serverlessClusterSvc,
		dedicatedClusterSvc,
		nextgenSvc,
		customStatusSvc,
		dedicatedCli,
		accountCli,
		nextgenCli,
		dedicatedRegionServer,
		clusterRepo,
	)
	internalCustomStatusServer := internalstatus.NewServer(customStatusSvc)
	internalRegionServer := internalregion.NewServer(serverlessCli, dedicatedCli, nextgenCli, accountCli)
	internalVpcPeeringServer := internalvpcpeering.NewServer(dedicatedCli)
	internalCompatServer := internalcompat.NewServer(dedicatedCli, clusterRepo)
	internalSpuServer := internalspu.NewServer(dedicatedCli)
	internalMaintenanceServer := internalmaintenance.NewServer(maintenanceWindowSvc)
	internalVpcServer := internalvpc.NewServer(dedicatedCli)
	internalCmekServer := internalcmek.NewServer(dedicatedCli)
	internalPrivateLinkServiceMigrationServer := internalprivatelinkservicemigration.NewServer(dedicatedCli, dedicatedClusterSvc)
	internalMigrationClusterServer := internalmigrationcluster.NewServer(migrationClusterSvc, dedicatedClusterSvc, accountCli)
	internalDedicatedToPremiumPrecheckServer := internaldedicatedtopremiumprecheck.NewServer(
		dedicatedToPremiumPrecheckSvc,
		dedicatedClusterSvc,
	)
	internalResourcePoolServer := internalresourcepool.NewServer(nextgenCli, clusterRepo, customStatusRepo, dbProvider)
	internalCapacityTemplateServer := internalcapacitytemplate.NewServer(nextgenCli)
	internalRcuServer := internalrcuquota.NewServer(nextgenCli)
	internalBackupServer := internalbackup.NewServer(nextgenCli, serverlessCli)
	internalPGBackupProxyServer := internalbackup.NewPGBackupProxyServer(nextgenCli, serverlessCli)
	internalDataSyncServer := internaldatasync.NewServer(dataSyncSvc, dedicatedClusterSvc)
	internalExportServer := internalexport.NewServer(nextgenCli)
	shadowPoolMgmtSvc := shadowpoolmgmtsvc.NewService(shadowPoolRepo)
	internalShadowPoolServer := internalshadowpool.NewServer(shadowPoolMgmtSvc)

	internalOrgConfigServer := internalorgconfig.NewServer(orgRuConfigRepo)

	internalFsRegionServer := internalfsregion.NewServer(infrarepo.NewFsRegionRepo(dbProvider))

	// init core server
	coreController := core.NewCoreServer(maintenanceWindowSvc)

	// init console server
	consoleOrchestrator := orchestrator.NewAPIOrchestrator(
		wflow,
		internalCustomStatusServer,
		dedicatedClusterServer,
		cluster.RegisterActions(dedicatedClusterServer, dedicatedTidbGroupServer),
	)
	bffServer := cluster.NewServer(
		dbProvider,
		consoleOrchestrator,
		auditLogSender,
		dedicatedClusterServer,
		dedicatedRegionServer,
		serverlessV1beta1Service,
		clusterRepo,
		dedicatedCli,
		featCli,
	)

	bffTiDBServer := tidbxinstance.NewTiDBServer(
		clusterRepo,
		dedicatedClusterServer,
		serverlessV1beta1Service,
		nextgenClusterServer,
		accountCli,
		dedicatedCli,
		nextgenCli,
		serverlessCli,
		serverlessClusterSvc,
		nextgenSvc,
		projectMigrationTaskRepo,
		wflow,
		auditLogSender,
	)

	bffRegionServer := tidbxregion.NewRegionServer(
		clusterRepo,
		dedicatedRegionServer,
		serverlessV1beta1Service,
		nextgenRegionServer,
		accountCli,
		dedicatedCli,
		nextgenCli,
		serverlessCli,
	)

	// Register gRPC servers
	gs := f.GrpcServer()

	// dedicated open api
	openapidedicatedv1beta1.RegisterClusterServiceServer(gs, dedicatedClusterServer)
	openapidedicatedv1beta1.RegisterNetworkContainerServiceServer(gs, dedicatedVpcServer)
	openapidedicatedv1beta1.RegisterRegionServiceServer(gs, dedicatedRegionServer)
	openapidedicatedv1beta1.RegisterMaintenanceServiceServer(gs, dedicatedMaintenanceServer)
	openapidedicatedv1beta1.RegisterTidbNodeGroupServiceServer(gs, dedicatedTidbGroupServer)
	openapidedicatedv1beta1.RegisterPrivateEndpointConnectionServiceServer(gs, dedicatedPrivateLinkServer)
	openapidedicatedv1beta1.RegisterDatabaseAuditLogServiceServer(gs, dedicatedAuditLogServer)
	openapidedicatedv1beta1.RegisterCustomerManagedEncryptionKeyServiceServer(gs, dedicatedCmekServer)

	// nextgen open api
	openapingv1beta2.RegisterTidbServiceServer(gs, nextgenClusterServer)
	openapingv1beta2.RegisterBackupServiceServer(gs, nextgenBackupServer)
	openapingv1beta2.RegisterExportServiceServer(gs, nextgenExportServer)
	openapingv1beta2.RegisterByocVpcPeeringServiceServer(gs, nextgenByocVpcPeeringServer)
	openapingv1beta2.RegisterPlanReplayerServiceServer(gs, nextgenPlanReplayerServer)
	openapingv1beta2.RegisterPublicConnectionSettingServiceServer(gs, nextgenPublicConnectionSettingServer)
	openapingv1beta2.RegisterPrivateEndpointConnectionServiceServer(gs, nextgenPrivateEndpointConnectionServer)
	openapingv1beta2.RegisterRegionServiceServer(gs, nextgenRegionServer)
	openapingv1beta2.RegisterResourcePoolServiceServer(gs, nextgenResourcePoolServer)
	openapingv1beta2.RegisterQuotaServiceServer(gs, nextgenQuotaServer)
	openapingv1beta2.RegisterDatabaseAuditLogServiceServer(gs, nextgenAuditLogServer)
	openapingv1beta2.RegisterLogRedactionPolicyServiceServer(gs, nextgenLogRedactionPolicyServer)
	openapingv1beta2.RegisterCustomerManagedEncryptionKeyServiceServer(gs, nextgenCmekServer)

	// fs open api
	openapifsv1beta2.RegisterRegionServiceServer(gs, fsRegionServer)

	// serverless
	openapiserverlessv1beta1.RegisterClusterServiceServer(gs, serverlessV1beta1Service)
	openapiserverlessv1beta1.RegisterShadowPoolServiceServer(gs, serverlessV1beta1Service)

	// zero
	openapizerov1beta1.RegisterZeroInstanceServiceServer(gs, zeroV1beta1Service)

	// internal api
	tidbmgmtservicev1.RegisterClusterServiceServer(gs, internalClusterServer)
	tidbmgmtservicev1.RegisterClusterCustomStatusServiceServer(gs, internalCustomStatusServer)
	tidbmgmtservicev1.RegisterRegionServiceServer(gs, internalRegionServer)
	tidbmgmtservicev1.RegisterVpcPeeringServiceServer(gs, internalVpcPeeringServer)
	tidbmgmtservicev1.RegisterDataPlaneServiceServer(gs, internalCompatServer)
	tidbmgmtservicev1.RegisterSpuServiceServer(gs, internalSpuServer)
	tidbmgmtservicev1.RegisterMaintenanceServiceServer(gs, internalMaintenanceServer)
	tidbmgmtservicev1.RegisterVpcServiceServer(gs, internalVpcServer)
	tidbmgmtservicev1.RegisterCmekServiceServer(gs, internalCmekServer)
	tidbmgmtservicev1.RegisterPrivateLinkServiceMigrationServiceServer(gs, internalPrivateLinkServiceMigrationServer)
	tidbmgmtservicev1.RegisterResourcePoolServiceServer(gs, internalResourcePoolServer)
	tidbmgmtservicev1.RegisterReservedCapacityTemplateServiceServer(gs, internalCapacityTemplateServer)
	tidbmgmtservicev1.RegisterMigrationClusterServiceServer(gs, internalMigrationClusterServer)
	tidbmgmtservicev1.RegisterDedicatedToPremiumPrecheckServiceServer(gs, internalDedicatedToPremiumPrecheckServer)
	tidbmgmtservicev1.RegisterRcuQuotaServiceServer(gs, internalRcuServer)
	tidbmgmtservicev1.RegisterBackupServiceServer(gs, internalBackupServer)
	tidbmgmtservicev1.RegisterServerlessPGBackupProxyServiceServer(gs, internalPGBackupProxyServer)
	tidbmgmtservicev1.RegisterDataSynchronizationServiceServer(gs, internalDataSyncServer)
	tidbmgmtservicev1.RegisterExportServiceServer(gs, internalExportServer)
	tidbmgmtservicev1.RegisterShadowPoolManagementServiceServer(gs, internalShadowPoolServer)
	tidbmgmtservicev1.RegisterOrganizationConfigServiceServer(gs, internalOrgConfigServer)
	tidbmgmtservicev1.RegisterFsRegionServiceServer(gs, internalFsRegionServer)

	// console api
	bffclusterv1beta1.RegisterClusterServiceServer(gs, bffServer)

	// one-console api
	bffv1beta2.RegisterTiDBServiceServer(gs, bffTiDBServer)
	bffv1beta2.RegisterRegionServiceServer(gs, bffRegionServer)

	// core api
	coreapi.RegisterCoreServiceServer(gs, coreController)
	// start sync maintenance window worker. It's ugly to start a worker in the Register function though.
	maintenanceWindowSvc.StartSyncMaintenanceWindowWorker()

	// dataplane http reverse proxy
	proxy.SetUpReverseProxy(f.GinEngine(), cfg, dedicatedCli, nextgenCli)

	shadowPoolWorker := shadowpool.NewWorker(clusterRepo, shadowPoolRepo, zeroRentRecordRepo, serverlessClusterSvc, cfg.ShadowPool)
	runner := worker.NewRunner(shadowPoolWorker)
	runner.StartWorker()

	return nil
}

func supportedChangefeedSinkTypes(cfg *config.DedicatedToPremiumPrecheckConfig) []string {
	if cfg == nil || len(cfg.SupportedChangefeedSinkTypes) == 0 {
		return []string{"S3", "KAFKA", "MYSQL"}
	}
	return cfg.SupportedChangefeedSinkTypes
}

func mustNewLeaseLocker(dbProvider tidbclouddb.TransProvider) lease.Locker {
	locker, err := lease.NewLocker(dbProvider)
	if err != nil {
		panic(err)
	}
	return locker
}

func NewPermissionCheckerInterceptor(
	cfg *config.Config,
	clusterRepo repository.ClusterRepository,
	maintenanceTaskRepo repository.MaintenanceTaskRepo,
) (grpc.UnaryServerInterceptor, error) {
	// Manual dependencies initialization.
	serverlessCli, err := globalserverlesscli.NewClient(cfg.Serverless)
	if err != nil {
		return nil, fmt.Errorf("init serverless global failed: %w", err)
	}

	dedicatedCli, err := globaldedicatedcli.NewClient(cfg.Dedicated)
	if err != nil {
		return nil, fmt.Errorf("init dedicated global failed: %w", err)
	}
	nextgenCli, err := globalnextgencli.NewClient(cfg.NextGen)
	if err != nil {
		return nil, fmt.Errorf("init nextgen global failed: %w", err)
	}

	// init permission checker
	interceptor := permissionmw.NewPermissionCheckInterceptor(&checker.CheckContext{
		ClusterRepo:          clusterRepo,
		MaintenanceTaskRepo:  maintenanceTaskRepo,
		DedicatedCli:         dedicatedCli,
		NextGenCli:           nextgenCli,
		ServerlessCli:        serverlessCli,
		DisableInternalCheck: cfg.ServerRuntimeConfig.DisableInternalCheck,
		ApiKey:               cfg.ServerRuntimeConfig.APIKey,
	})

	return interceptor, nil
}
