package cluster

import (
	"context"

	"github.com/tidbcloud/pkgv2/db"
	"go.opentelemetry.io/otel"

	globalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/serverless/v1"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/adapter"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/repository"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/service/sqluser"
	workflowimpl "github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/service/workflow"
	"github.com/tidbcloud/tidb-management-service/utilities/featuregate"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

var Tracer = otel.Tracer("DomainService.Cluster")

type Service interface {
	Create(
		ctx context.Context,
		createReq *globalserverlessv1.ServerlessServiceCreateRequest,
	) (*globalserverlessv1.ServerlessServiceCluster, error)
	List(
		ctx context.Context,
		listReq *globalserverlessv1.ServerlessServiceListRequest,
	) ([]*globalserverlessv1.ServerlessServiceCluster, error)
	Delete(ctx context.Context, id string, validateOnly bool) (*globalserverlessv1.ServerlessServiceCluster, error)
	Update(
		ctx context.Context,
		updateReq *globalserverlessv1.ServerlessServiceUpdateRequest,
	) (*globalserverlessv1.ServerlessServiceUpdateResponse, error)
	Count(ctx context.Context, countReq *globalserverlessv1.ServerlessServiceCountClustersRequest) (int64, error)
	CheckCloudStoragePermission(
		ctx context.Context,
		req *globalserverlessv1.CheckCloudStoragePermissionRequest,
	) (*globalserverlessv1.CheckCloudStoragePermissionResponse, error)
	UpdateAuditLogConfig(
		ctx context.Context,
		req *globalserverlessv1.UpdateAuditLogConfigRequest,
	) (*globalserverlessv1.UpdateAuditLogConfigResponse, error)
}

type clusterServiceImpl struct {
	flow             workflow.Workflow
	regionalService  adapter.RegionalService
	sys9Lifecycle    adapter.Sys9Lifecycle
	encryptorService adapter.EncryptorService
	serverlessFacade adapter.ServerlessService
	brFacade         adapter.BRService
	billingFacade    adapter.BillingService

	cloudProviderRepo repository.CloudProviderRepo
	clusterRepo       repository.ClusterRepo
	regionRepo        repository.RegionRepo

	eventCommitter adapter.WALCommitter

	dbUserSvc            sqluser.Service
	accountSvc           adapter.AccountService
	clusterProxyProvider adapter.ClusterProxyProvider

	transaction db.Transactioner
	featureGate featuregate.Service
}

func NewClusterService(
	flow workflow.Workflow,
	cloudProviderRepo repository.CloudProviderRepo,
	regionRepo repository.RegionRepo,
	clusterRepo repository.ClusterRepo,
	encryptorFacade adapter.EncryptorService,
	regionFacade adapter.RegionalService,
	sys9Lifecycle adapter.Sys9Lifecycle,
	serverlessFacade adapter.ServerlessService,
	brFacade adapter.BRService,
	billingFacade adapter.BillingService,
	dbUserSvc sqluser.Service,
	accountSvc adapter.AccountService,
	clusterProxyProvider adapter.ClusterProxyProvider,
	transaction db.Transactioner,
	committer adapter.WALCommitter,
	featureGate featuregate.Service,
) (Service, error) {
	if err := workflowimpl.RegisterDags(
		flow,
		clusterRepo,
		regionFacade,
		sys9Lifecycle,
		accountSvc,
		encryptorFacade,
		dbUserSvc,
		serverlessFacade,
		brFacade,
		committer,
		transaction,
		clusterProxyProvider,
	); err != nil {
		return nil, err
	}
	return &clusterServiceImpl{
		flow:                 flow,
		sys9Lifecycle:        sys9Lifecycle,
		encryptorService:     encryptorFacade,
		serverlessFacade:     serverlessFacade,
		brFacade:             brFacade,
		billingFacade:        billingFacade,
		regionalService:      regionFacade,
		clusterRepo:          clusterRepo,
		regionRepo:           regionRepo,
		dbUserSvc:            dbUserSvc,
		accountSvc:           accountSvc,
		clusterProxyProvider: clusterProxyProvider,
		cloudProviderRepo:    cloudProviderRepo,
		transaction:          transaction,
		eventCommitter:       committer,
		featureGate:          featureGate,
	}, nil
}
