package serverless

import (
	"context"

	openapiserverlessv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/serverless/v1beta1"
	serverlesscluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/serverless/cluster"
	serverlessprovider "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/serverless/provider"
	serverlessshadowpool "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/serverless/shadowpool"
	serverlessuser "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/app/openapi/serverless/user"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/account"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/eventbus"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/serverlessglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/repository"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/customstatus"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/serverless/cluster"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/serverless/user"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/config"
)

type Server struct {
	clusterSvc serverlesscluster.Server
	userSvc    serverlessuser.User
	regionSvc  serverlessprovider.Server
	poolSvc    serverlessshadowpool.Server
}

type OpenAPIServer interface {
	openapiserverlessv1beta1.ClusterServiceServer
	openapiserverlessv1beta1.ShadowPoolServiceServer
}

func NewServer(
	serverlessCli serverlessglobal.ServerlessGlobal,
	clusterService cluster.Service,
	clusterRepo repository.ClusterRepository,
	userService user.Service,
	customStatus customstatus.Service,
	shadowPoolRepo repository.ShadowPoolRepository,
	accountCli account.Client,
	auditLogSender eventbus.ConsoleAuditLogSender,
	oneConsoleConfig *config.OneConsoleConfig,
) OpenAPIServer {
	return &Server{
		clusterSvc: serverlesscluster.NewServer(clusterService, customStatus, auditLogSender, accountCli, oneConsoleConfig),
		userSvc:    serverlessuser.NewUser(clusterService, userService, auditLogSender),
		regionSvc:  serverlessprovider.NewServer(serverlessCli, accountCli),
		poolSvc:    serverlessshadowpool.NewServer(shadowPoolRepo, clusterRepo),
	}
}

func (s Server) CreateCluster(
	ctx context.Context,
	req *openapiserverlessv1beta1.CreateClusterRequest,
) (*openapiserverlessv1beta1.Cluster, error) {
	return s.clusterSvc.CreateCluster(ctx, req)
}

func (s Server) ListClusters(
	ctx context.Context,
	req *openapiserverlessv1beta1.ListClustersRequest,
) (*openapiserverlessv1beta1.ListClustersResponse, error) {
	return s.clusterSvc.ListClusters(ctx, req)
}

func (s Server) GetCluster(
	ctx context.Context,
	req *openapiserverlessv1beta1.GetClusterRequest,
) (*openapiserverlessv1beta1.Cluster, error) {
	return s.clusterSvc.GetCluster(ctx, req)
}

func (s Server) BindTags(
	ctx context.Context,
	req *openapiserverlessv1beta1.BindTagsRequest,
) (*openapiserverlessv1beta1.BindTagsResponse, error) {
	return s.clusterSvc.BindTags(ctx, req)
}

func (s Server) UnbindTags(
	ctx context.Context,
	req *openapiserverlessv1beta1.UnbindTagsRequest,
) (*openapiserverlessv1beta1.UnbindTagsResponse, error) {
	return s.clusterSvc.UnbindTags(ctx, req)
}

func (s Server) DeleteCluster(
	ctx context.Context,
	req *openapiserverlessv1beta1.DeleteClusterRequest,
) (*openapiserverlessv1beta1.Cluster, error) {
	return s.clusterSvc.DeleteCluster(ctx, req)
}

func (s Server) PartialUpdateCluster(
	ctx context.Context,
	req *openapiserverlessv1beta1.PartialUpdateClusterRequest,
) (*openapiserverlessv1beta1.Cluster, error) {
	return s.clusterSvc.UpdateCluster(ctx, req)
}

func (s Server) ListRegions(
	ctx context.Context,
	req *openapiserverlessv1beta1.ListRegionsRequest,
) (*openapiserverlessv1beta1.ListRegionsResponse, error) {
	return s.regionSvc.ListRegions(ctx, req)
}

func (s Server) ListCloudProviders(
	ctx context.Context,
	req *openapiserverlessv1beta1.ListCloudProvidersRequest,
) (*openapiserverlessv1beta1.ListCloudProvidersResponse, error) {
	return s.regionSvc.ListCloudProviders(ctx, req)
}

func (s Server) ChangeRootPassword(
	ctx context.Context,
	req *openapiserverlessv1beta1.ChangeRootPasswordRequest,
) (*openapiserverlessv1beta1.ChangeRootPasswordResponse, error) {
	return s.userSvc.ChangeRootPassword(ctx, req)
}

func (s Server) RotateRootPassword(
	ctx context.Context,
	req *openapiserverlessv1beta1.RotateRootPasswordRequest,
) (*openapiserverlessv1beta1.RotateRootPasswordResponse, error) {
	return s.userSvc.RotateRootPassword(ctx, req)
}

func (s Server) RedeemRootPassword(
	ctx context.Context,
	req *openapiserverlessv1beta1.RedeemRootPasswordRequest,
) (*openapiserverlessv1beta1.RedeemRootPasswordResponse, error) {
	return s.userSvc.RedeemRootPassword(ctx, req)
}

func (s Server) BatchCreateClusters(
	ctx context.Context,
	request *openapiserverlessv1beta1.BatchCreateClustersRequest,
) (*openapiserverlessv1beta1.BatchCreateClustersResponse, error) {
	return s.clusterSvc.BatchCreateClusters(ctx, request)
}

func (s Server) BatchGetClusters(
	ctx context.Context,
	request *openapiserverlessv1beta1.BatchGetClustersRequest,
) (*openapiserverlessv1beta1.BatchGetClustersResponse, error) {
	return s.clusterSvc.BatchGetClusters(ctx, request)
}

func (s Server) BatchDeleteClusters(
	ctx context.Context,
	request *openapiserverlessv1beta1.BatchDeleteClustersRequest,
) (*openapiserverlessv1beta1.BatchDeleteClustersResponse, error) {
	return s.clusterSvc.BatchDeleteClusters(ctx, request)
}

func (s Server) ClaimClusterFromZero(ctx context.Context,
	request *openapiserverlessv1beta1.ClaimClusterFromZeroRequest,
) (*openapiserverlessv1beta1.Cluster, error) {
	return s.clusterSvc.ClaimClusterFromZero(ctx, request)
}

func (s Server) TakeoverClusterFromPool(ctx context.Context,
	request *openapiserverlessv1beta1.TakeoverClusterFromPoolRequest,
) (*openapiserverlessv1beta1.Cluster, error) {
	return s.clusterSvc.TakeoverClusterFromPool(ctx, request)
}

func (s Server) CreateShadowPool(
	ctx context.Context,
	req *openapiserverlessv1beta1.CreateShadowPoolRequest,
) (*openapiserverlessv1beta1.ShadowPool, error) {
	return s.poolSvc.CreateShadowPool(ctx, req)
}

func (s Server) ListShadowPools(
	ctx context.Context,
	req *openapiserverlessv1beta1.ListShadowPoolsRequest,
) (*openapiserverlessv1beta1.ListShadowPoolsResponse, error) {
	return s.poolSvc.ListShadowPools(ctx, req)
}

func (s Server) GetShadowPool(
	ctx context.Context,
	req *openapiserverlessv1beta1.GetShadowPoolRequest,
) (*openapiserverlessv1beta1.ShadowPool, error) {
	return s.poolSvc.GetShadowPool(ctx, req)
}

func (s Server) DeleteShadowPool(
	ctx context.Context,
	req *openapiserverlessv1beta1.DeleteShadowPoolRequest,
) (*openapiserverlessv1beta1.DeleteShadowPoolResponse, error) {
	return s.poolSvc.DeleteShadowPool(ctx, req)
}

func (s Server) UpdateShadowPool(
	ctx context.Context,
	req *openapiserverlessv1beta1.UpdateShadowPoolRequest,
) (*openapiserverlessv1beta1.ShadowPool, error) {
	return s.poolSvc.UpdateShadowPool(ctx, req)
}

func (s Server) ReplaceShadowPoolInitSqls(
	ctx context.Context,
	req *openapiserverlessv1beta1.ReplaceShadowPoolInitSqlsRequest,
) (*openapiserverlessv1beta1.ShadowPool, error) {
	return s.poolSvc.ReplaceShadowPoolInitSqls(ctx, req)
}

func (s Server) ReplaceShadowPoolInstanceDemand(
	ctx context.Context,
	req *openapiserverlessv1beta1.ReplaceShadowPoolInstanceDemandRequest,
) (*openapiserverlessv1beta1.ShadowPool, error) {
	return s.poolSvc.ReplaceShadowPoolInstanceDemand(ctx, req)
}
