package action

import (
	"fmt"

	"braces.dev/errtrace"
	"github.com/tidbcloud/fastflow/pkg/entity/run"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/encoding/protojson"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/adapter/dedicatedglobal"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/constant"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/workflow"
)

type DeleteDedicatedClusterAction struct {
	dedicatedCli dedicatedglobal.DedicatedGlobal
}

func NewDeleteDedicatedClusterAction(dedicatedCli dedicatedglobal.DedicatedGlobal) *DeleteDedicatedClusterAction {
	return &DeleteDedicatedClusterAction{
		dedicatedCli: dedicatedCli,
	}
}

func (c *DeleteDedicatedClusterAction) Name() string {
	return constant.TaskDedicatedGlobalDeleteCluster
}

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

	tilog.Info(cctx, "delete dedicated cluster action start")
	requestJson, ok := ctx.GetVar(constant.KeyRequest)
	if !ok {
		return fmt.Errorf("delete dedicated request is not found")
	}

	var request globaldedicatedv1.DeleteClusterRequest
	if err := protojson.Unmarshal([]byte(requestJson), &request); err != nil {
		return fmt.Errorf("unmarshal delete dedicated request failed: %w", err)
	}

	request.ValidateOnly = false
	_, err := c.dedicatedCli.DeleteCluster(cctx, &request)
	if err != nil {
		if s, ok := status.FromError(err); ok {
			// skip if dedicated cluster is not found
			if s.Code() == codes.Code(bizerr.ErrCodeRecordNotFound) {
				tilog.Warn(
					cctx,
					"dedicated cluster is not found",
					zap.String("cluster_id", fmt.Sprint(request.ClusterId)),
				)
				return nil
			}
		}
		return errtrace.Wrap(err)
	}

	tilog.Info(cctx, "delete dedicated cluster action end")
	return nil
}
