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"
	schemav1 "github.com/tidbcloud/cluster-service-ng/pkg/storage/etcd/schema/v1"
	"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 CreateSharedPoolConfigAction struct {
	sharedPoolRepo      repo.SharedPoolRepo
	clusterConfigClient clusterconfig.Client
}

const CreateSharedPoolConfigName = "create-shared-pool-config"

func NewCreateSharedPoolConfigAction(
	sharedPoolRepo repo.SharedPoolRepo,
	clusterConfigClient clusterconfig.Client,
) actions.Action {
	return &CreateSharedPoolConfigAction{
		sharedPoolRepo:      sharedPoolRepo,
		clusterConfigClient: clusterConfigClient,
	}
}

func (a *CreateSharedPoolConfigAction) Name() string {
	return CreateSharedPoolConfigName
}

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

	sharedPoolId, err := args.GetString(workflow.SharedPoolIdKey)
	if err != nil {
		return fmt.Errorf("failed to get sharedPool id: %w", err)
	}

	configCenterMetaProfileId, _ := args.GetString(workflow.ConfigCenterMetaProfileIdKey)

	// load sharedPool
	sharedPool, err := a.sharedPoolRepo.Load(ctx, sharedPoolId, false)
	if err != nil {
		return fmt.Errorf("failed to load sharedPool: %w", err)
	}

	sharedPoolStr, err := args.GetString(workflow.SharedPoolKey)
	if err != nil {
		return fmt.Errorf("failed to get sharedPool: %w", err)
	}

	var tempSharedPool entity.SharedPool
	err = protojson.Unmarshal([]byte(sharedPoolStr), &tempSharedPool)
	if err != nil {
		tilog.Error(ctx, "failed to unmarshal sharedPool", zap.Error(err))
		return fmt.Errorf("failed to unmarshal sharedPool: %w", err)
	}
	sharedPool.ComponentGroups = tempSharedPool.GetComponentGroups()
	sharedPool.Version = tempSharedPool.GetVersion()

	tenantId, _ := args.GetString(workflow.TenantIdKey)
	if tenantId == "" {
		tenantId = schemav1.MultiTenantTag
	}

	err = a.clusterConfigClient.CreateClusterMeta(ctx, sharedPool, tenantId, configCenterMetaProfileId)
	if err != nil {
		tilog.Error(ctx, "failed to create cluster config", zap.Error(err))
		return fmt.Errorf("failed to create cluster config: %w", err)
	}

	return nil
}
