package pdfun

import (
	"context"
	"strings"
	"time"

	. "github.com/onsi/gomega"
	. "github.com/pingcap/endless/pkg/matcher"
	. "github.com/pingcap/endless/pkg/matcher/metrics"
	. "github.com/pingcap/endless/pkg/util"
	"github.com/pingcap/endless/testcase/oltp/oltppkg"
	"github.com/pingcap/log"
	"github.com/pingcap/test-infra/sdk/resource"
	"golang.org/x/sync/errgroup"
)

func OLTP_PAUSE_RESUME_SCHEDULER_FUN_001(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	workloadRunParms oltppkg.WorkloadRunParms,
) {
	runTime := 120 * time.Minute
	ctxAll, cancelAll := context.WithTimeout(ctx, runTime)
	defer cancelAll()
	defer oltppkg.SetPDScheduler(tc, "resume", 0)

	g, ctxg := errgroup.WithContext(ctxAll)

	var workloadCheckParms oltppkg.WorkloadCheckParameters
	if caseCmdParms.WorkloadType.Type[0] == "tpcc" {
		workloadCheckParms = oltppkg.WorkloadCheckParameters{
			IsCheck:   true,
			IgnoreErr: append(strings.Split(caseCmdParms.TpccParms.IgnoreErrors, ","), "fail"),
		}
	} else {
		workloadCheckParms = oltppkg.WorkloadCheckParameters{
			IsCheck:   true,
			IgnoreErr: append(strings.Split(caseCmdParms.SysbenchParms.IgnoreErrors, ","), "fail"),
		}
	}

	oltppkg.FunCommonCheck(ctxg, tc, g, runTime, workloadRunParms.Cmdpr, workloadCheckParms)

	g.Go(WithGinkgoRecover(func() {
		ConsistentlyWithMetrics(tc).
			ShouldNot(AllComponentRestart().WithCtx(ctxg))
	}))

	startTime := time.Now().Add(10 * time.Minute)
	oltppkg.WaitFor(ctxg, "Warm workload", 20*time.Minute)

	oltppkg.LogAndBy("Step 1: pause scheduler 1 hours")
	oltppkg.SetPDScheduler(tc, "pause", 3600)
	oltppkg.WaitFor(ctxg, "Wait for resume the scheduler", 60*time.Minute)
	oltppkg.SetPDScheduler(tc, "resume", 0)

	oltppkg.LogAndBy("Step 2: check if workload balance")
	oltppkg.WaitForWorkloadBalance(ctx, tc, caseCmdParms.WorkloadType.Type[0], g, runTime, 30*time.Minute, 0.8)

	log.Info("Step 3: Check if qps down with the beginning.")
	g.Go(WithGinkgoRecover(func() {
		oltppkg.WaitFor(ctxg, "Waiting for balance", 30*time.Minute)
		oltppkg.RepeatQpsDurCheckWithAbsTime(ctxg, runTime, startTime, tc, 0.5)
	}))
	Expect(g.Wait()).Should(BeNil())
}
