package action

import (
	"fmt"

	"github.com/tidbcloud/cluster-service-ng/domain/entity"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow"
	"github.com/tidbcloud/cluster-service-ng/pkg/clusterconfig"
	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/actions"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/repo"
	"github.com/tidbcloud/cluster-service-ng/pkg/utils"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
	"google.golang.org/protobuf/encoding/protojson"
)

type CreateTiDBClusterMetaAction struct {
	tidbGroupRepo       repo.TiDBGroupRepo
	sharedPoolRepo      repo.SharedPoolRepo
	clusterConfigClient clusterconfig.Client
}

const CreateTiDBClusterMetaName = "create-tidb-cluster-meta"

func NewCreateTiDBClusterMetaAction(
	tidbGroupRepo repo.TiDBGroupRepo,
	sharedPoolRepo repo.SharedPoolRepo,
	clusterConfigClient clusterconfig.Client,
) actions.Action {
	return &CreateTiDBClusterMetaAction{
		tidbGroupRepo:       tidbGroupRepo,
		sharedPoolRepo:      sharedPoolRepo,
		clusterConfigClient: clusterConfigClient,
	}
}

func (a *CreateTiDBClusterMetaAction) Name() string {
	return CreateTiDBClusterMetaName
}

// Invoke creates tidb cluster cr in dataplane
func (a *CreateTiDBClusterMetaAction) Invoke(args actions.ActionArgs) error {
	// generate context
	ctx := utils.GenerateContext(args)
	tilog.Info(ctx, "create tidb cluster meta action invoked")

	tidbClusterStr, err := args.GetString(workflow.TiDBClusterKey)
	if err != nil {
		return fmt.Errorf("failed to get tidb cluster: %w", err)
	}

	var tidbCluster entity.TiDBCluster
	err = protojson.Unmarshal([]byte(tidbClusterStr), &tidbCluster)
	if err != nil {
		tilog.Error(ctx, "failed to unmarshal tidb cluster", zap.Error(err))
		return fmt.Errorf("failed to unmarshal tidb cluster: %w", err)
	}

	sharedPool, err := a.sharedPoolRepo.Load(ctx, tidbCluster.GetSharedPoolId(), false)
	if err != nil {
		tilog.Error(ctx, "failed to load shared pool for tidb cluster meta", zap.String("sharedPoolId", tidbCluster.GetSharedPoolId()), zap.Error(err))
		return fmt.Errorf("failed to load shared pool for tidb cluster meta: %w", err)
	}

	err = a.clusterConfigClient.CreateTiDBClusterMeta(ctx, sharedPool, &tidbCluster)
	if err != nil {
		tilog.Error(ctx, "failed to create tidb cluster meta", zap.Error(err))
		return fmt.Errorf("failed to create tidb cluster meta: %w", err)
	}

	return nil
}
