package betting

import (
	"context"
	"fmt"

	"github.com/pingcap/test-infra/sdk/core"
	"github.com/pingcap/test-infra/sdk/resource"
	"golang.org/x/sync/errgroup"

	"github.com/pingcap/endless/pkg/workloadnode"
	"github.com/pingcap/endless/pkg/workloadnode/cmdstr"
)

// FIXME: too many arguments in this function.
func RunWorkload(
	suiteTestCtx core.TestContext,
	tc resource.TiDBCluster,
	ctx context.Context,

	bettingOpts cmdstr.BettingOptions,
	subcmd cmdstr.GoycsbSubcmd,
) error {
	g, gctx := errgroup.WithContext(ctx)

	dbURL, err := tc.ServiceURL(resource.DBAddr)
	if err != nil {
		return err
	}
	bettingOpts.MySQL.Host = dbURL.Hostname()
	bettingOpts.MySQL.Port = dbURL.Port()

	for i := 0; i < bettingOpts.Clients; i++ {
		clientID := fmt.Sprintf("%d", i)

		// Tune options based on client id.
		opts := bettingOpts // Copy a new opts object.
		opts.UnitNamePrefix = "unit" + clientID + "_"
		name := "workload" + clientID
		// Please ensure there are enough workload node.
		// Client_{i} runs on wokrload{i}.
		wn := suiteTestCtx.Resource(name).(resource.WorkloadNode)
		goycsb := cmdstr.NewGoycsb("/go-ycsb")
		if subcmd == cmdstr.GoycsbLoad {
			goycsb.Load("mysql")
		} else {
			goycsb.Run("mysql")
		}
		cmdString := goycsb.BettingOptions(&opts).String()
		cmd := workloadnode.CommandContext(gctx, cmdString)

		// HACK: Kill old go-ycsb process.
		if err := workloadnode.CommandContext(ctx, "pkill -9 go-ycsb || true").Run(wn); err != nil {
			return nil
		}

		// Start client on workloadnode.
		if err := cmd.Start(wn); err != nil {
			return err
		}

		g.Go(func() error {
			return cmd.Wait()
		})
	}

	return g.Wait()
}
