package tidbgroup

import (
	"context"

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

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/adapter/eventbus"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/adapter/regionserver"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/cluster"
	endpointrepo "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/endpoint"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/region"
	tidbgrouprepo "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/tidbgroup"
	clustersvc "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/service/cluster"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/pkg/config"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/featuregate"
	"github.com/tidbcloud/tidb-management-service/utilities/idgenerator"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

type Service interface {
	CreateTidbNodeGroup(
		ctx context.Context,
		req *globaldedicatedv1.CreateTidbNodeGroupRequest,
	) (*globaldedicatedv1.TidbNodeGroup, bizerr.BizError)
	UpdateTidbNodeGroup(
		ctx context.Context,
		req *globaldedicatedv1.UpdateTidbNodeGroupRequest,
	) (*globaldedicatedv1.TidbNodeGroup, bizerr.BizError)
	DeleteTidbNodeGroup(
		ctx context.Context,
		req *globaldedicatedv1.DeleteTidbNodeGroupRequest,
	) (*emptypb.Empty, bizerr.BizError)
	ListTidbNodeGroups(
		ctx context.Context,
		req *globaldedicatedv1.ListTidbNodeGroupsRequest,
	) (*globaldedicatedv1.ListTidbNodeGroupsResponse, bizerr.BizError)
	DisableTidbGroupDNS(
		ctx context.Context,
		req *globaldedicatedv1.DisableTidbGroupDNSRequest,
	) (*emptypb.Empty, bizerr.BizError)
	EnableTidbGroupDNS(
		ctx context.Context,
		req *globaldedicatedv1.EnableTidbGroupDNSRequest,
	) (*emptypb.Empty, bizerr.BizError)
	GetPrivateLinkIPAddressType(
		ctx context.Context,
		req *globaldedicatedv1.GetPrivateLinkIPAddressTypeRequest,
	) (*globaldedicatedv1.TidbGroupPrivateLinkIPAddressTypeStatus, bizerr.BizError)
	SetPrivateLinkIPAddressType(
		ctx context.Context,
		req *globaldedicatedv1.SetPrivateLinkIPAddressTypeRequest,
	) (*globaldedicatedv1.TidbGroupPrivateLinkIPAddressTypeStatus, bizerr.BizError)
}

type service struct {
	clusterRepo             cluster.Repo
	componentRepo           cluster.ComponentRepo
	tidbGroupRepo           tidbgrouprepo.Repo
	trafficFilterRepo       endpointrepo.TrafficFilterRepo
	privateLinkEndpointRepo endpointrepo.PrivateLinkEndpointRepo
	regionRepo              region.Repo
	regionServerCli         regionserver.Client
	idGeneratorFacade       idgenerator.IDGenerator
	clusterService          clustersvc.Service
	workflow                workflow.Workflow
	transaction             db.Transactioner
	featureGate             featuregate.Service

	eventCommitter eventbus.WALCommitter

	cfg *config.Config
}

func NewService(
	clusterRepo cluster.Repo,
	componentRepo cluster.ComponentRepo,
	tidbGroupRepo tidbgrouprepo.Repo,
	trafficFilterRepo endpointrepo.TrafficFilterRepo,
	privateLinkEndpointRepo endpointrepo.PrivateLinkEndpointRepo,
	regionRepo region.Repo,
	regionServerCli regionserver.Client,
	idGeneratorFacade idgenerator.IDGenerator,
	clusterService clustersvc.Service,
	workflowImpl workflow.Workflow,
	transaction db.Transactioner,
	eventCommitter eventbus.WALCommitter,
	cfg *config.Config,
	featureGate featuregate.Service,
) Service {
	return &service{
		clusterRepo:             clusterRepo,
		componentRepo:           componentRepo,
		tidbGroupRepo:           tidbGroupRepo,
		trafficFilterRepo:       trafficFilterRepo,
		privateLinkEndpointRepo: privateLinkEndpointRepo,
		regionRepo:              regionRepo,
		regionServerCli:         regionServerCli,
		idGeneratorFacade:       idGeneratorFacade,
		clusterService:          clusterService,
		workflow:                workflowImpl,
		transaction:             transaction,
		featureGate:             featureGate,
		eventCommitter:          eventCommitter,
		cfg:                     cfg,
	}
}
