package gcp

import (
	"time"

	"github.com/avast/retry-go/v4"
	"github.com/shiningrush/fastflow/pkg/entity/run"
	"github.com/tidbcloud/dataflow-service/app/models/bucket"
	"github.com/tidbcloud/dataflow-service/app/models/domain"
	"github.com/tidbcloud/dataflow-service/app/repo"
	"github.com/tidbcloud/dataflow-service/app/workflow"
	"github.com/tidbcloud/dataflow-service/app/workflow/action"
	"github.com/tidbcloud/dataflow-service/app/workflow/action/bucket/base"
	"github.com/tidbcloud/dataflow-service/internal/db"
	"go.uber.org/zap"
)

type DeleteBucketAction struct {
	base.BaseAction
	GcpBucketManager bucket.GCPBucketManagerModel
}

func NewDeleteBucketAction(
	transProvider db.TransProvider,
	bucketRepo repo.BucketRepo,
	gcpBucketManager bucket.GCPBucketManagerModel,
) *DeleteBucketAction {
	return &DeleteBucketAction{
		BaseAction:       base.NewBaseAction(transProvider, bucketRepo),
		GcpBucketManager: gcpBucketManager,
	}
}

func (a *DeleteBucketAction) Name() string {
	return workflow.ActionDeleteBucketGCP
}

//nolint:gomnd
func (a *DeleteBucketAction) Run(ctx run.ExecuteContext, params interface{}) error {
	logger := action.GetLogger(ctx).Named(a.Name())
	logger.Info("action run")
	bucket, err := a.QueryBucket(ctx, logger)
	if err != nil {
		return err
	}

	req := &domain.DeleteGCPBucketReq{
		Name: bucket.Name,
	}
	err = retry.Do(func() error {
		if err := a.GcpBucketManager.DeleteBucketIgnoreNotFound(ctx.Context(), req); err != nil {
			logger.Warn("delete bucket error", zap.String("name", bucket.Name), zap.Error(err))
			return err
		}
		return nil
	},
		retry.Context(ctx.Context()),
		retry.DelayType(retry.BackOffDelay),
		retry.Delay(time.Second*2),
		retry.Attempts(20),
		retry.MaxDelay(time.Minute*2),
		retry.OnRetry(func(n uint, err error) {
			logger.Info("action run error", zap.Uint("retry_times", n))
		}),
		retry.LastErrorOnly(true),
	)
	if err != nil {
		logger.Error("action run error", zap.Error(err))
		return err
	}

	logger.Info("action run finished")
	return nil
}
