package testcase

import (
	"time"

	"github.com/google/uuid"

	"github.com/pingcap/test-infra/caselib/pkg/host"
	"github.com/pingcap/test-infra/caselib/pkg/model/ticdc"
	"github.com/pingcap/test-infra/caselib/pkg/model/workload"
	"github.com/pingcap/test-infra/caselib/pkg/steps"
	"github.com/pingcap/test-infra/caselib/pkg/utils"
	"github.com/pingcap/test-infra/caselib/ticdc/common"
	"github.com/pingcap/test-infra/common/model/resource"
	"github.com/pingcap/tiflow/cdc/model"
)

// CDC works parallelized with BR backup upstream or restore downstream
// Create upstream TiDB cluster/downstream TiDB/workload/br/mc
// Create a changefeed
// Create database named `workload`
// Run workload prepare
// Run BR backup upstream parallelized with workload run (CDC has sync task to work)
// Run BR restore downstream parallelized with workload run (CDC has sync task to work)
// Waiting for workload finish
// Check consistency
var _ = common.AddTestCase("cdc_br_parallelized", func() steps.Step {
	var (
		dbNameVar            = common.DBName
		changeFeedID         = "cdc-br-parallelized"
		brHost               = &resource.ResourceHandle{}
		mcHost               = &resource.ResourceHandle{}
		backupOpts           = &host.BackupFullOpts{}
		backupDownstreamOpts = &host.BackupFullOpts{}
		mcRmOpts             = &host.McRmOpts{}
		uniq                 = uuid.New().String()
	)
	return steps.
		NewBuilder().
		LoadEnv().
		LoadResourceFromEnv("TI_PARAM_RES_upstream", common.ResourceHandleSource).
		LoadResourceFromEnv("TI_PARAM_RES_downstream", common.ResourceHandleMySQL).
		LoadResourceFromEnv("TI_PARAM_RES_workload", common.ResourceHandleWorkload).
		LoadResourceFromEnv(utils.ResourcePrefix+"br", brHost).
		LoadResourceFromEnv(utils.ResourcePrefix+"mc", mcHost).
		LoadResourceFromEnv(utils.ParamPrefix+"br_opts", backupOpts).
		LoadResourceFromEnv(utils.ParamPrefix+"br_downstream_opts", backupDownstreamOpts).
		NewUniqPath(&backupOpts.Storage, uniq).
		NewUniqPath(&mcRmOpts.Path, uniq).
		NewUniqPath(&backupDownstreamOpts.Storage, uniq).
		NewUniqPath(&mcRmOpts.Path, uniq).
		DropUserDatabases(common.ResourceHandleSource).
		InitCDCComponents(common.ResourceHandleSource, common.ResourceHandleMySQL).
		OperateChangeFeed(&ticdc.ChangeFeedCreateFlags{SinkType: ticdc.SinkTypeMySQL, ID: changeFeedID}).
		CreateDatabase(common.ResourceHandleSource, common.DBName).
		InitWorkload(common.ResourceHandleWorkload).
		RunWorkload(common.Spec.GetWorkloadOption(workload.CommandTypePrepare)).
		Parallel(
			steps.NewBrBackupFull(brHost, common.ResourceHandleSource, backupOpts),
			steps.NewSwitchOwner(common.ResourceHandleSource, 20*time.Second),
			steps.NewRunWorkload(common.Spec.GetWorkloadOption(workload.CommandTypeRun)),
		).
		Parallel(
			steps.NewBrBackupFull(brHost, common.ResourceHandleMySQL, backupDownstreamOpts),
			steps.NewSwitchOwner(common.ResourceHandleSource, 20*time.Second),
			steps.NewRunWorkload(common.Spec.GetWorkloadOption(workload.CommandTypeRun)),
		).
		SendFinishMark(dbNameVar).
		Sleep(20*time.Minute).
		WaitFinishMark(common.ResourceHandleMySQL, dbNameVar, 3*time.Hour).
		CheckConsistency(common.ResourceHandleSource, common.ResourceHandleMySQL, dbNameVar).
		DropDatabasesIfExists(common.ResourceHandleSource, &dbNameVar).
		Sleep(1 * time.Minute).
		OperateChangeFeed(&ticdc.ChangeFeedAdminJobFlags{JobType: model.AdminRemove, ID: changeFeedID, ForceRemove: true}).
		Build()
},
)
