package privatelink

import (
	"context"

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

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/adapter/regionserver"
	clusterrepo "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"
	regionrepo "github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/region"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/tidbgroup"
	"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/idgenerator"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

var tracer = otel.Tracer("domain.privatelink")

type Service interface {
	CreateClusterConnection(ctx context.Context, clusterId uint64) bizerr.BizError
	CreatePrivateLinkEndpoint(
		ctx context.Context,
		req *globaldedicatedv1.CreatePrivateLinkEndpointRequest,
	) (*globaldedicatedv1.PrivateLinkEndpoint, bizerr.BizError)
	CreateService(
		ctx context.Context,
		req *globaldedicatedv1.CreatePrivateLinkServiceRequest,
	) (*globaldedicatedv1.PrivateLinkService, bizerr.BizError)
	DeleteEndpoint(ctx context.Context, req *globaldedicatedv1.DeletePrivateLinkEndpointRequest) bizerr.BizError
	DeleteService(ctx context.Context, req *globaldedicatedv1.DeletePrivateLinkServiceRequest) bizerr.BizError
	ListPrivateLinkEndpoints(
		ctx context.Context,
		request *globaldedicatedv1.ListPrivateLinkEndpointsRequest,
	) ([]*globaldedicatedv1.PrivateLinkEndpoint, bizerr.BizError)
	ListTidbNodeGroupPrivateLinkEndpoints(
		ctx context.Context,
		request *globaldedicatedv1.ListTidbNodeGroupPrivateLinkEndpointsRequest,
	) (*globaldedicatedv1.PrivateLinkService, []*globaldedicatedv1.PrivateLinkEndpoint, bizerr.BizError)
	GetPrivateLinkService(
		ctx context.Context,
		request *globaldedicatedv1.GetPrivateLinkServiceRequest,
	) (*globaldedicatedv1.PrivateLinkService, bizerr.BizError)
	RejectVpcEndpointConnections(
		ctx context.Context,
		req *globaldedicatedv1.RejectVpcEndpointConnectionsRequest,
	) bizerr.BizError
	PausePrivateLinkService(
		ctx context.Context,
		req *globaldedicatedv1.PausePrivateLinkServiceRequest,
	) bizerr.BizError
	PurgePrivateLinkServiceMetadata(
		ctx context.Context,
		req *globaldedicatedv1.PurgePrivateLinkServiceMetadataRequest,
	) bizerr.BizError
}

func NewService(
	cfg *config.Config,
	clusterRepo clusterrepo.Repo,
	privateLinkEndpointRepo endpointrepo.PrivateLinkEndpointRepo,
	tidbGroupRepo tidbgroup.Repo,
	regionRepo regionrepo.Repo,
	regionServerCli regionserver.Client,
	wflow workflow.Workflow,
	idGeneratorFacade idgenerator.IDGenerator,
	transaction db.Transactioner,
) Service {
	return &service{
		cfg:                     cfg,
		clusterRepo:             clusterRepo,
		privateLinkEndpointRepo: privateLinkEndpointRepo,
		tidbGroupRepo:           tidbGroupRepo,
		regionRepo:              regionRepo,
		regionServerCli:         regionServerCli,
		workflow:                wflow,
		idGeneratorFacade:       idGeneratorFacade,
		transaction:             transaction,
	}
}

type service struct {
	cfg                     *config.Config
	clusterRepo             clusterrepo.Repo
	privateLinkEndpointRepo endpointrepo.PrivateLinkEndpointRepo
	tidbGroupRepo           tidbgroup.Repo
	regionRepo              regionrepo.Repo
	regionServerCli         regionserver.Client
	workflow                workflow.Workflow
	idGeneratorFacade       idgenerator.IDGenerator
	transaction             db.Transactioner
}
