package region

import (
	"context"

	"github.com/tidbcloud/pkgv2/db"
	"google.golang.org/protobuf/types/known/emptypb"

	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/adapter/metrics"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/adapter/regionalserver"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/repository/cluster"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/repository/region"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/repository/resourcepool"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/idgenerator"
	utilworkflow "github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

type Service interface {
	GetRegionByLogicalName(
		ctx context.Context,
		req *globalngv1.GetRegionByLogicalNameRequest,
	) (*entity.Region, bizerr.BizError)
	GetRegionByClusterId(
		ctx context.Context,
		req *globalngv1.GetRegionByClusterIdRequest,
	) (*entity.Region, bizerr.BizError)
	ListRegions(
		ctx context.Context,
		req *globalngv1.ListRegionsRequest,
	) ([]*entity.Region, bizerr.BizError)
	ListCloudProviders(
		ctx context.Context,
		req *globalngv1.ListCloudProvidersRequest,
	) ([]*entity.CloudProvider, bizerr.BizError)
	RegisterCloudProvider(
		ctx context.Context,
		req *globalngv1.RegisterCloudProviderRequest,
	) (*entity.CloudProvider, bizerr.BizError)
	RegisterRegion(
		ctx context.Context,
		req *globalngv1.RegisterRegionRequest,
	) (*entity.Region, bizerr.BizError)
	UpdateRegion(
		ctx context.Context,
		req *globalngv1.UpdateRegionRequest,
	) (*entity.Region, bizerr.BizError)
	DeleteRegion(
		ctx context.Context,
		req *globalngv1.DeleteRegionRequest,
	) (*emptypb.Empty, bizerr.BizError)
	SelectRegionByOrgId(
		ctx context.Context,
		req *globalngv1.SelectRegionByOrgIdRequest,
	) (*entity.Region, bizerr.BizError)
	UpdateRegionOpsAuditLogSetting(
		ctx context.Context,
		request *globalngv1.UpdateRegionOpsAuditLogSettingRequest,
	) (*globalngv1.UpdateRegionOpsAuditLogSettingResponse, bizerr.BizError)
	RegisterRegionProviderIdentity(
		ctx context.Context,
		request *globalngv1.RegisterRegionProviderIdentityRequest,
	) (*globalngv1.RegionProviderIdentity, bizerr.BizError)
	ListRegionProviderIdentities(
		ctx context.Context,
		request *globalngv1.ListRegionProviderIdentitiesRequest,
	) (*globalngv1.ListRegionProviderIdentitiesResponse, bizerr.BizError)
	PickRegionProviderIdentity(ctx context.Context,
		regionId uint64,
		tenantId uint64) (*globalngv1.RegionProviderIdentity, bizerr.BizError)
	ListRegionCapacities(
		ctx context.Context,
		req *globalngv1.ListRegionCapacitiesRequest,
	) (*globalngv1.ListRegionCapacitiesResponse, bizerr.BizError)
	ListByocVcpuPools(
		ctx context.Context,
		req *globalngv1.ListByocVcpuPoolsRequest,
	) (*globalngv1.ListByocVcpuPoolsResponse, bizerr.BizError)
	GetByocSharedComponentScaleConstraints(
		ctx context.Context,
		req *globalngv1.GetByocSharedComponentScaleConstraintsRequest,
	) (*globalngv1.ByocSharedComponentScaleConstraints, bizerr.BizError)
	ScaleByocSharedComponents(
		ctx context.Context,
		req *globalngv1.ScaleByocSharedComponentsRequest,
	) (*globalngv1.ScaleByocSharedComponentsResponse, bizerr.BizError)
	ListNodeSpecs(
		ctx context.Context,
		req *globalngv1.ListNodeSpecsRequest,
	) (*globalngv1.ListNodeSpecsResponse, bizerr.BizError)
}

type service struct {
	regionRepo                 region.Repo
	regionProviderIdentityRepo region.ProviderIdentityRepo
	clusterRepo                cluster.Repo
	resourcePoolRepo           resourcepool.Repo
	resourcePoolStrategyRepo   resourcepool.StrategyRepo
	transaction                db.Transactioner
	nextgenCli                 regionalserver.Client
	idGeneratorAdapter         idgenerator.IDGenerator
	metricsClient              metrics.Client
	workflow                   utilworkflow.Workflow
}

func NewService(
	regionRepo region.Repo,
	clusterRepo cluster.Repo,
	regionProviderIdentityRepo region.ProviderIdentityRepo,
	resourcePoolRepo resourcepool.Repo,
	resourcePoolStrategyRepo resourcepool.StrategyRepo,
	transaction db.Transactioner,
	nextgenCli regionalserver.Client,
	idGeneratorAdapter idgenerator.IDGenerator,
	metricsClient metrics.Client,
	workflow utilworkflow.Workflow,
) Service {
	return &service{
		regionRepo:                 regionRepo,
		regionProviderIdentityRepo: regionProviderIdentityRepo,
		clusterRepo:                clusterRepo,
		resourcePoolRepo:           resourcePoolRepo,
		resourcePoolStrategyRepo:   resourcePoolStrategyRepo,
		transaction:                transaction,
		nextgenCli:                 nextgenCli,
		idGeneratorAdapter:         idGeneratorAdapter,
		metricsClient:              metricsClient,
		workflow:                   workflow,
	}
}
