package action

import (
	"strconv"

	"github.com/tidbcloud/fastflow/pkg/entity/run"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"

	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/adapter/eventbus"
	"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"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/repository/region"
	"github.com/tidbcloud/tidb-management-service/dedicated-global-service/domain/service/workflow/common"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

const (
	PauseClusterTc = "pause_cluster_tc"
)

type PauseClusterTcAction struct {
	clusterRepo clusterrepo.Repo
	regionRepo  region.Repo
	regionalCli regionserver.Client
	committer   eventbus.WALCommitter
}

func NewPauseClusterTcAction(
	clusterRepo clusterrepo.Repo,
	regionRepo region.Repo,
	regionalCli regionserver.Client,
	committer eventbus.WALCommitter,
) *PauseClusterTcAction {
	return &PauseClusterTcAction{
		clusterRepo: clusterRepo,
		regionRepo:  regionRepo,
		regionalCli: regionalCli,
		committer:   committer,
	}
}

func (a *PauseClusterTcAction) Name() string {
	return PauseClusterTc
}

func (a *PauseClusterTcAction) ParameterNew() any {
	return &common.ClusterIdParameter{}
}

func (a *PauseClusterTcAction) Run(ctx run.ExecuteContext, params any) error {
	cctx, span := workflow.GenerateContext(ctx)

	clusterId, err := common.GetClusterId(params)
	if err != nil {
		tilog.Error(cctx, "failed to get cluster id", zap.Error(err))
		return err
	}

	tilog.Info(cctx, "start to pause cluster", zap.Uint64("cluster_id", clusterId))
	defer func() {
		tilog.Info(cctx, "end to pause cluster", zap.Uint64("cluster_id", clusterId))
		span.End()
	}()

	cluster, err := a.clusterRepo.Get(cctx, clusterId, false)
	if err != nil {
		tilog.Error(cctx, "failed to get cluster", zap.Error(err))
		return err
	}

	regionEntity, err := a.regionRepo.SelectRegionById(cctx, cluster.RegionId, cluster.GetOrganizationId())
	if err != nil {
		tilog.Error(cctx, "failed to find region", zap.Error(err))
		return err
	}

	clusterIdStr := strconv.FormatUint(clusterId, 10)
	if err := a.regionalCli.PauseClusterTc(cctx, regionEntity, clusterIdStr); err != nil {
		tilog.Error(cctx, "failed to pause cluster tc", zap.String("cluster_id", clusterIdStr), zap.Error(err))
		return err
	}

	tilog.Info(cctx, "cluster tc is paused", zap.String("cluster_id", clusterIdStr))
	return nil
}
