package loadsplit

import (
	"context"
	"time"

	. "github.com/pingcap/endless/pkg/matcher"
	"github.com/pingcap/endless/testcase/oltp/oltppkg"
	"github.com/pingcap/test-infra/sdk/resource"
	_ "github.com/pingcap/test-infra/sdk/resource/impl/k8s"
	"golang.org/x/sync/errgroup"
)

func OLTP_LOAD_BASE_SPLIT_MIX_FUN(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 1000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  false,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              200,
		RegionThreshhold:          8,
		CpuBalanceCheckThreshhold: 1.0,
		CpuBalanceCheckWarmup:     5 * time.Minute,
		ChaosInject:               false,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)
}

func OLTP_LOAD_BASE_SPLIT_PURE_SCAN_LITTLE(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 1000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  true,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              300,
		RegionThreshhold:          8,
		CpuBalanceCheckThreshhold: 1.0,
		CpuBalanceCheckWarmup:     5 * time.Minute,
		ScanWithIndex:             false,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)
}

func OLTP_LOAD_BASE_SPLIT_PURE_SCAN_LARGE(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 10000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  true,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              300,
		RegionThreshhold:          8,
		CpuBalanceCheckThreshhold: 1.0,
		CpuBalanceCheckWarmup:     5 * time.Minute,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)
}

func OLTP_LOAD_BASE_SPLIT_PURE_SCAN_INDEX_LITTLE(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 1000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  true,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              300,
		ScanWithIndex:             true,
		RegionThreshhold:          20,
		CpuBalanceCheckThreshhold: 1.0,
		CpuBalanceCheckWarmup:     5 * time.Minute,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)
}

func OLTP_LOAD_BASE_SPLIT_PURE_SCAN_INDEX_LARGE(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 10000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  true,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              300,
		ScanWithIndex:             true,
		RegionThreshhold:          6,
		CpuBalanceCheckThreshhold: 1.0,
		CpuBalanceCheckWarmup:     5 * time.Minute,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)
}

func OLTP_LOAD_BASE_SPLIT_MIX_REL_001(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 1000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  false,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              200,
		ChaosInject:               true,
		RegionThreshhold:          8,
		CpuBaseEnableRandom:       true,
		CpuOverloadRandom:         false,
		CpuBalanceCheckThreshhold: 1.0,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)

	oltppkg.SetAndVerifyConfigOnline(tc, "tikv", "split.region-cpu-overload-threshold-ratio", "0.05")
	oltppkg.WaitFor(ctx, "waiting for balance", 10*time.Minute)

	g, ctxg := errgroup.WithContext(ctx)
	opt.TiKVCpuBalanceCheck(ctxg, tc, 10*time.Minute, g)
	opt.RegionCountShouldMoreThan(ctxg, tc, 10*time.Minute, g)
	Try(g.Wait())
}

func OLTP_LOAD_BASE_SPLIT_MIX_REL_002(
	ctx context.Context,
	tc resource.TiDBCluster,
	caseCmdParms oltppkg.CaseCmdParms,
	benchToolset resource.WorkloadNode,
) {
	opt := LoadSplitOpt{
		TableSize:                 1000,
		TableNum:                  1,
		TableName:                 "sbtest1",
		PureScan:                  false,
		CpuOverloadRatio:          "0.05",
		ScanParallel:              200,
		ChaosInject:               true,
		RegionThreshhold:          8,
		CpuBaseEnableRandom:       false,
		CpuOverloadRandom:         true,
		CpuBalanceCheckThreshhold: 1.0,
	}
	opt.LoadSplitTest(ctx, tc, caseCmdParms, benchToolset)

	oltppkg.WaitFor(ctx, "waiting to set cpu overload threshhold ratio to 0.5", 2*time.Minute)
	oltppkg.SetAndVerifyConfigOnline(tc, "tikv", "split.region-cpu-overload-threshold-ratio", "0.05")
	oltppkg.WaitFor(ctx, "waiting for balance", 10*time.Minute)

	g, ctxg := errgroup.WithContext(ctx)
	opt.TiKVCpuBalanceCheck(ctxg, tc, 10*time.Minute, g)
	opt.RegionCountShouldMoreThan(ctxg, tc, 10*time.Minute, g)
	Try(g.Wait())
}
