package enable

import (
	"context"

	"github.com/shiningrush/fastflow/pkg/entity/run"
	"github.com/tidbcloud/dataflow-service/app/models/domain"
	"github.com/tidbcloud/dataflow-service/app/models/tidb"
	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	"github.com/tidbcloud/dataflow-service/app/workflow"
	"github.com/tidbcloud/dataflow-service/app/workflow/action"
	"github.com/tidbcloud/dataflow-service/app/workflow/action/backup/base"
	"github.com/tidbcloud/dataflow-service/pkg/log"
	"go.uber.org/zap"
)

type StartGCAction struct {
	base.BaseAction
	clusterGCSwitchModel tidb.ClusterGCSwitchModel
}

func NewStartGCActionAction(base base.BaseAction, clusterGCSwitchModel tidb.ClusterGCSwitchModel) *StartGCAction {
	return &StartGCAction{BaseAction: base, clusterGCSwitchModel: clusterGCSwitchModel}
}

func (a *StartGCAction) Name() string {
	return workflow.ActionStartGCforPitBackup
}

func (a *StartGCAction) startGC(ctx context.Context, logBackup *entity.LogBackup) error {
	logger := log.GetLogger(ctx)
	logger.Info("start gc for log backup start")
	defer logger.Info("start gc for log backup finished")
	_, err := a.clusterGCSwitchModel.Enable(ctx, &domain.EnableTiDBClusterGCSwitchReq{
		TenantID:  logBackup.TenantID.Uint64(),
		ProjectID: logBackup.ProjectID.Uint64(),
		ClusterID: logBackup.ClusterID.Uint64(),

		BusinessID:   logBackup.ID.Uint64(),
		BusinessType: entity.TiDBClusterGCSwitchBusinessTypePiTBackup,
	})
	return err
}

func (a *StartGCAction) Run(ctx run.ExecuteContext, params interface{}) error {
	logger := action.GetLogger(ctx).Named(a.Name())
	logger.Info("action run start")
	defer logger.Info("action run finished")

	ctxWithLogger := log.WithLogger(ctx.Context(), logger)
	retryErr := action.InvokeRunActionWithExponentialRetry(ctxWithLogger, logger, func() error {
		logBackup, err := a.QueryLogBackup(ctx, logger, workflow.KeyEnableLogBackupID)
		if err != nil {
			logger.Error("query log backup error", zap.Error(err))
			return err
		}
		return a.startGC(ctxWithLogger, logBackup)
	})
	if retryErr != nil {
		logger.Error("action run error", zap.Error(retryErr))
		return retryErr
	}
	return retryErr
}
