package azure

import (
	"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/pkgv2/db"
	"go.uber.org/zap"
)

const (
	// Azure Storage Account is a namespace for different storage services (file, disk, blob etc)
	// A container must be exist before writing data into a storage account
	// We can roughly treat storage account + container as bucket on other clouds
	// We specify a fixed container name for br
	containerPolicyName = "br"
)

type CreateContainerAction struct {
	base.BaseAction
	azureBucketManager bucket.AzureBucketManagerModel
}

func NewCreateContainerAction(
	transProvider db.TransProvider,
	bucketRepo repo.BucketRepo,
	azureBucketManager bucket.AzureBucketManagerModel,
) *CreateContainerAction {
	return &CreateContainerAction{
		BaseAction:         base.NewBaseAction(transProvider, bucketRepo),
		azureBucketManager: azureBucketManager,
	}
}

func (a *CreateContainerAction) Name() string {
	return workflow.ActionCreateContainer
}

func (a *CreateContainerAction) Run(ctx run.ExecuteContext, params interface{}) error {
	logger := action.GetLogger(ctx).Named(a.Name())
	logger.Info("Run action create_azure_container")
	err := action.InvokeRunActionWithRetry(ctx.Context(), logger, func() error {
		bkt, err := a.QueryBucket(ctx, logger)
		if err != nil {
			return err
		}
		req := &domain.CreateAzureBucketContainerReq{
			Name:           bkt.Name,
			SubscriptionID: *bkt.CloudAccountID,
		}
		logger.Info("create azure container")
		err = a.azureBucketManager.CreateContainer(ctx.Context(), req)
		if err != nil {
			logger.Warn("create container error", zap.Any("bucket id", bkt.ID), zap.Error(err))
			return err
		}
		return nil
	})
	if err != nil {
		logger.Error("action run error", zap.Error(err))
		return err
	}
	logger.Info("action run finished")
	return nil
}
