package ngoperation

import (
	"context"
	"fmt"

	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
	mgmtv1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
)

const (
	cassandraLabelKey   = "tidb.cloud/cassandra"
	cassandraLabelValue = "true"
)

var (
	ActionAddCassandraLabel opent.ActionMetadata = opent.ActionMetadata{
		Name: "add_cassandra_label",
		Type: opent.ActionTypeAuto,
	}
)

type addCassandraLabel struct {
	actions.BaseAction
	comps *actions.Components
}

func NewAddCassandraLabel(comps *actions.Components) actions.AutoAction {
	return &addCassandraLabel{comps: comps}
}

func (a *addCassandraLabel) Metadata() opent.ActionMetadata {
	return ActionAddCassandraLabel
}

func (a *addCassandraLabel) PreCheck(ctx context.Context, instance *opent.Instance) error {
	_, err := actions.GetClusterID(instance)
	if err != nil {
		return err
	}
	return a.validateClient()
}

func (a *addCassandraLabel) Start(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	clusterID, err := actions.GetClusterID(instance)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}
	if err = a.validateClient(); err != nil {
		return actions.FailedActionResult(err), nil
	}

	cluster, err := a.comps.CoreSvc.Mgmt.Cluster.AddClusterLabels(ctx, &mgmtv1.AddClusterLabelsRequest{
		ClusterId: clusterID,
		Labels: map[string]string{
			cassandraLabelKey: cassandraLabelValue,
		},
	})
	if err != nil {
		return actions.FailedActionResult(err), nil
	}
	if cluster.GetLabels()[cassandraLabelKey] != cassandraLabelValue {
		return actions.FailedActionResult(fmt.Errorf("returned cluster labels do not contain %s=%s", cassandraLabelKey, cassandraLabelValue)), nil
	}

	return actions.NewActionResult(opent.ActionStatusSucceeded, fmt.Sprintf("added cluster label %s=%s", cassandraLabelKey, cassandraLabelValue), nil), nil
}

func (a *addCassandraLabel) Result(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	return actions.SucceededActionResult(nil), nil
}

func (a *addCassandraLabel) validateClient() error {
	if a.comps == nil || a.comps.CoreSvc == nil || a.comps.CoreSvc.Mgmt == nil || a.comps.CoreSvc.Mgmt.Cluster == nil {
		return fmt.Errorf("cluster metadata client is required for cassandra label operations")
	}
	return nil
}
