package workflow

import (
	"github.com/tidbcloud/fastflow/pkg/entity/run"
	"github.com/tidbcloud/pkgv2/db"

	"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"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/service/workflow/action"
	"github.com/tidbcloud/tidb-management-service/serverless-global-service/domain/service/workflow/dag"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

// Global action instances - each action is created exactly once
type actionInstances struct {
	preCreateCluster    run.Action
	createCluster       run.Action
	postCreateCluster   run.Action
	updateCluster       run.Action
	deleteCluster       run.Action
	rotateRootPwdStart  run.Action
	rotateRootPwdPoll   run.Action
	rotateRootPwdRedeem run.Action
}

func RegisterDags(
	flow workflow.Workflow,
	clusterRepo repository.ClusterRepo,
	regionalService adapter.RegionalService,
	sys9Lifecycle adapter.Sys9Lifecycle,
	accountSvc adapter.AccountService,
	encryptorService adapter.EncryptorService,
	dbUserSvc sqluser.Service,
	serverlessFacade adapter.ServerlessService,
	brFacade adapter.BRService,
	eventCommitter adapter.WALCommitter,
	transactioner db.Transactioner,
	clusterProxyProvider adapter.ClusterProxyProvider) error {
	// Initialize all action instances exactly once
	actions := &actionInstances{
		preCreateCluster: action.NewPreCreateClusterAction(clusterRepo, serverlessFacade, brFacade),
		createCluster:    action.NewCreateClusterAction(clusterRepo, regionalService, sys9Lifecycle),
		postCreateCluster: action.NewPostCreateClusterAction(
			clusterRepo,
			regionalService,
			sys9Lifecycle,
			accountSvc,
			encryptorService,
			dbUserSvc,
			eventCommitter,
			transactioner,
			clusterProxyProvider,
		),
		updateCluster:       action.NewUpdateClusterAction(clusterRepo, regionalService, serverlessFacade, brFacade, eventCommitter),
		deleteCluster:       action.NewDeleteClusterAction(clusterRepo, regionalService, serverlessFacade, sys9Lifecycle),
		rotateRootPwdStart:  action.NewRotateRootPasswordStartAction(clusterRepo, sys9Lifecycle),
		rotateRootPwdPoll:   action.NewRotateRootPasswordPollAction(clusterRepo, sys9Lifecycle),
		rotateRootPwdRedeem: action.NewRotateRootPasswordRedeemAction(clusterRepo, sys9Lifecycle, encryptorService, eventCommitter),
	}

	// Build action slices for each DAG by referencing the shared instances
	createClusterActions := []run.Action{
		actions.preCreateCluster,
		actions.createCluster,
		actions.postCreateCluster,
	}

	updateClusterActions := []run.Action{
		actions.updateCluster,
	}

	deleteClusterActions := []run.Action{
		actions.deleteCluster,
	}

	rotateRootPasswordActions := []run.Action{
		actions.rotateRootPwdStart,
		actions.rotateRootPwdPoll,
		actions.rotateRootPwdRedeem,
	}

	// Register DAGs with shared action instances
	if err := flow.RegisterDag(
		dag.NewCreateClusterDag(), createClusterActions); err != nil {
		return err
	}

	if err := flow.RegisterDag(
		dag.NewUpdateClusterDag(), updateClusterActions); err != nil {
		return err
	}

	if err := flow.RegisterDag(
		dag.NewDeleteClusterDag(), deleteClusterActions); err != nil {
		return err
	}

	if err := flow.RegisterDag(
		dag.NewRotateRootPasswordDag(), rotateRootPasswordActions); err != nil {
		return err
	}

	return nil
}
