package action

import (
	"errors"
	"fmt"

	"braces.dev/errtrace"
	"github.com/samber/lo"
	"github.com/tidbcloud/fastflow/pkg/entity/run"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"google.golang.org/protobuf/encoding/protojson"

	globalserverlessv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/serverless/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/remoteencryptor"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/serverlessglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/constant"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

type CreateServerlessClusterAction struct {
	serverlessCli serverlessglobal.ServerlessGlobal
	encryptor     remoteencryptor.Client
}

func NewCreateServerlessClusterAction(
	serverlessCli serverlessglobal.ServerlessGlobal,
	encryptor remoteencryptor.Client,
) *CreateServerlessClusterAction {
	return &CreateServerlessClusterAction{
		serverlessCli: serverlessCli,
		encryptor:     encryptor,
	}
}

func (c *CreateServerlessClusterAction) Name() string {
	return constant.TaskServerlessGlobalCreateCluster
}

func (c *CreateServerlessClusterAction) Run(ctx run.ExecuteContext, params any) error {
	cctx, span := workflow.GenerateContext(ctx)
	defer span.End()

	tilog.Info(cctx, "create serverless cluster action start")
	requestJson, ok := ctx.GetVar(constant.KeyRequest)
	if !ok {
		return errtrace.Wrap(errors.New("create serverless request is not found"))
	}

	var request globalserverlessv1.ServerlessServiceCreateRequest
	if err := protojson.Unmarshal([]byte(requestJson), &request); err != nil {
		return fmt.Errorf("unmarshal create serverless request failed: %w", err)
	}

	// decrypt root password if request
	if request.GetRootPassword() != "" {
		rootPassword, err := c.encryptor.DecryptBase64(cctx, request.GetRootPassword())
		if err != nil {
			return fmt.Errorf("decrypt root password failed: %w", err)
		}
		request.RootPassword = lo.ToPtr(rootPassword)
	}

	_, err := c.serverlessCli.CreateCluster(cctx, &request)
	if err != nil {
		return errtrace.Wrap(err)
	}

	tilog.Info(cctx, "create serverless cluster action end")
	return nil
}
