//nolint:funlen,gomnd
package bucket

import (
	"fmt"

	"github.com/shiningrush/fastflow/pkg/entity"
	"github.com/shiningrush/fastflow/pkg/entity/run"
	"github.com/tidbcloud/dataflow-service/app/container"
	"github.com/tidbcloud/dataflow-service/app/workflow"
	"github.com/tidbcloud/dataflow-service/app/workflow/action"
	restoreCreate "github.com/tidbcloud/dataflow-service/app/workflow/action/restore/create"
	pitrCreate "github.com/tidbcloud/dataflow-service/app/workflow/action/restore/pitr/create"
)

func GetRestorePitBackupDag() (*entity.Dag, []run.Action) {
	actions := []run.Action{
		restoreCreate.NewCheckAndCreateCluster(
			container.Global().TransProvider,
			container.Global().RestoreRepo,
			container.Global().CoreGrpcClient,
			container.Global().MgmtSvcGrpcClient,
			container.Global().FeatureGate,
		),
		restoreCreate.NewInitRestoreConfig(
			container.Global().RestoreRepo,
			container.Global().MgmtSvcGrpcClient,
			container.Global().ConfigCenterManager,
		),
		action.MustNewActionWrapperV2(restoreCreate.NewAddBucketPolicy(
			container.Global().TransProvider,
			container.Global().RestoreRepo,
			container.Global().BucketModelProxy,
			container.Global().MgmtSvcGrpcClient,
			container.Global().TiDBClusterInfraClient,
		)),
		action.MustNewActionWrapperV2(pitrCreate.NewRunCompactBackupForRestore(
			container.Global().TransProvider,
			container.Global().CRRFSettingRepo,
			container.Global().RestoreRepo,
			container.Global().BackupRepo,
			container.Global().CompactBackupModel,
			container.Global().CompactBackupRepo,
			container.Global().MgmtSvcGrpcClient,
		)),
		pitrCreate.NewRunRestoring(
			container.Global().TransProvider,
			container.Global().RestoreRepo,
			container.Global().BackupRepo,
			container.Global().BucketRepo,
			container.Global().LogBackupRepo,
			container.Global().CompactBackupRepo,
			container.Global().Encryptor,
			container.Global().RestoreRegionalFacade,
			container.Global().EventCenterPublisher,
			container.Global().CoreGrpcClient,
			container.Global().MgmtSvcGrpcClient,
			container.Global().ConfigCenterManager,
			container.Global().TiDBClusterInfraClient,
			container.Global().FeatureGate,
		),
		restoreCreate.NewRestoreSqlBindings(
			container.Global().TransProvider,
			container.Global().RestoreRepo,
			container.Global().CoreGrpcClient,
			container.Global().MgmtSvcGrpcClient,
			container.Global().ClusterProxyModel,
			container.Global().FeatureGate,
		),
		pitrCreate.NewDeleteCompactionForPiTR(
			container.Global().RestoreRepo,
			container.Global().CompactBackupModel,
		),
		restoreCreate.NewRecycleBucketPolicy(
			container.Global().TransProvider,
			container.Global().RestoreRepo,
			container.Global().BucketModelProxy,
			container.Global().MgmtSvcGrpcClient,
			container.Global().TiDBClusterInfraClient,
		),
		restoreCreate.NewDeleteClusterJobForRestoring(
			container.Global().TransProvider,
			container.Global().RestoreRepo,
			container.Global().CoreGrpcClient,
			container.Global().MgmtSvcGrpcClient,
			container.Global().ClusterJobModel,
			container.Global().FeatureGate,
		),
		pitrCreate.NewRestorePitBackupFinalStep(
			container.Global().TransProvider,
			container.Global().CoreGrpcClient,
			container.Global().MgmtSvcGrpcClient,
			container.Global().RestoreRepo,
			container.Global().FeatureGate,
		),
	}
	dag := &entity.Dag{
		BaseInfo: entity.BaseInfo{
			ID: workflow.DagPitRestore,
		},
		Name:   workflow.DagPitRestore,
		Status: entity.DagStatusNormal,
		Vars: map[string]entity.DagVar{
			workflow.KeyActionAddBucketPolicyForRestoringSwitch:    {},
			workflow.KeyActionDeleteBucketPolicyForRestoringSwitch: {},
			workflow.KeyRestoreID:                                  {},
			workflow.KeyRestoreToClusterType:                       {},
			workflow.BRVersion:                                     {},
			workflow.BRImageTag:                                    {},
			workflow.BRCustomOptions:                               {},
		},
		Tasks: []entity.Task{
			{
				ID:         workflow.ActionCheckAndCreateClusterForRestoring,
				ActionName: workflow.ActionCheckAndCreateClusterForRestoring,
				Params: map[string]interface{}{
					workflow.KeyRestoreID: fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
				},
				TimeoutSecs: 60 * 90,
			},
			{
				ID:          workflow.ActionInitRestoreConfig,
				ActionName:  workflow.ActionInitRestoreConfig,
				DependOn:    []string{workflow.ActionCheckAndCreateClusterForRestoring},
				TimeoutSecs: 30,
			},
			{
				ID:         workflow.ActionAddBucketPolicyForRestoring,
				ActionName: workflow.ActionAddBucketPolicyForRestoring,
				Params: map[string]interface{}{
					workflow.KeyRestoreID: fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
				},
				DependOn:    []string{workflow.ActionCheckAndCreateClusterForRestoring},
				TimeoutSecs: 60 * 5,
			},
			{
				ID:         workflow.ActionRunCompactBackupForPiTR,
				ActionName: workflow.ActionRunCompactBackupForPiTR,
				Params: map[string]interface{}{
					workflow.KeyRestoreID: fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
				},
				DependOn:    []string{workflow.ActionAddBucketPolicyForRestoring},
				TimeoutSecs: 60 * 5,
			},
			{
				ID:         workflow.ActionRunPitRestoring,
				ActionName: workflow.ActionRunPitRestoring,
				Params: map[string]interface{}{
					workflow.KeyRestoreID:            fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
					workflow.KeyRestoreToClusterType: fmt.Sprintf("{{%v}}", workflow.KeyRestoreToClusterType),
					workflow.BRVersion:               fmt.Sprintf("{{%v}}", workflow.BRVersion),
					workflow.BRImageTag:              fmt.Sprintf("{{%v}}", workflow.BRImageTag),
					workflow.BRCustomOptions:         fmt.Sprintf("{{%v}}", workflow.BRCustomOptions),
				},
				DependOn:    []string{workflow.ActionAddBucketPolicyForRestoring, workflow.ActionInitRestoreConfig, workflow.ActionRunCompactBackupForPiTR},
				TimeoutSecs: 60 * 60 * 24,
			},
			{
				ID:         workflow.ActionRestoreSqlBindings,
				ActionName: workflow.ActionRestoreSqlBindings,
				Params: map[string]interface{}{
					workflow.KeyRestoreID: fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
				},
				DependOn:    []string{workflow.ActionRunPitRestoring},
				TimeoutSecs: 60,
			},
			{
				ID:          workflow.ActionDeleteCompactionForPiTR,
				ActionName:  workflow.ActionDeleteCompactionForPiTR,
				DependOn:    []string{workflow.ActionRunPitRestoring},
				TimeoutSecs: 3 * 60, // fire-and-forget async compactions/ deletion only; migrations/ is cleaned by CreateCompactBackupTask
			},
			{
				ID:         workflow.ActionDeleteClusterJobForRestoring,
				ActionName: workflow.ActionDeleteClusterJobForRestoring,
				Params: map[string]interface{}{
					workflow.KeyRestoreID: fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
				},
				DependOn:    []string{workflow.ActionRestoreSqlBindings, workflow.ActionDeleteCompactionForPiTR},
				TimeoutSecs: 30,
			},
			{
				ID:         workflow.ActionRestorePitBackupFinalStep,
				ActionName: workflow.ActionRestorePitBackupFinalStep,
				Params: map[string]interface{}{
					workflow.KeyRestoreID: fmt.Sprintf("{{%v}}", workflow.KeyRestoreID),
				},
				DependOn:    []string{workflow.ActionDeleteClusterJobForRestoring},
				TimeoutSecs: 30,
			},
		},
	}
	return dag, actions
}
