package action

import (
	"fmt"
	"time"

	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow"
	"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"
)

type PreCreateTiDBGroupAction struct {
	tidbClusterRepo repo.TiDBClusterRepo
}

const PreCreateTiDBGroupActionName = "pre-create-tidbgroup"

func NewPreCreateTiDBGroupAction(
	tidbClusterRepo repo.TiDBClusterRepo,
) actions.Action {
	return &PreCreateTiDBGroupAction{
		tidbClusterRepo: tidbClusterRepo,
	}
}

func (a *PreCreateTiDBGroupAction) Name() string {
	return PreCreateTiDBGroupActionName
}

func (a *PreCreateTiDBGroupAction) Invoke(args actions.ActionArgs) error {
	// generate context
	ctx := utils.GenerateContext(args)
	tilog.Info(ctx, "pre create tidb group action invoked")

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

	// check tidb cluster status
	tidbCluster, err := a.tidbClusterRepo.Load(ctx, tidbClusterId, false)
	if err != nil {
		tilog.Error(ctx, "failed to load tidb cluster", zap.String("tidbClusterId", tidbClusterId), zap.Error(err))
		return fmt.Errorf("failed to load tidb cluster: %w", err)
	}

	if tidbCluster.GetPhase() == apiv1.Cluster_UNAVAILABLE || tidbCluster.GetPhase() == apiv1.Cluster_CREATING {
		tilog.Error(ctx, "tidb cluster is unavailable or creating", zap.String("tidbClusterId", tidbCluster.GetId()), zap.String("phase", tidbCluster.GetPhase().String()))
		// Optional: wait a bit before returning an error
		// TODO: remove this sleep in production code
		time.Sleep(20 * time.Second)

		return fmt.Errorf("tidb cluster %s is not available", tidbCluster.GetId())
	}

	return nil
}
