package restore

import (
	"context"

	"github.com/samber/lo"
	core_event "github.com/tidbcloud/core-svc/event"
	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	"github.com/tidbcloud/dataflow-service/app/container"
	"github.com/tidbcloud/dataflow-service/app/models/domain"
	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	"github.com/tidbcloud/dataflow-service/pkg/log"
	"go.uber.org/zap"
)

type RestoreWithClusterDeleting struct{}

func (r *RestoreWithClusterDeleting) Name() string {
	return "RestoreWithClusterDeleting"
}

func (r *RestoreWithClusterDeleting) WatchForEvents() []core_event.ClusterEventType {
	return []core_event.ClusterEventType{core_event.ClusterEventTypeDeleting}
}

func (r *RestoreWithClusterDeleting) Match(event *core_event.ClusterEvent) bool {
	return lo.Contains(r.WatchForEvents(), event.EventType)
}

func (r *RestoreWithClusterDeleting) Execute(
	ctx context.Context, event *core_event.ClusterEvent, cluster *core.Cluster,
) error {
	logger := log.GetLogger(ctx).Named("RestoreWithClusterDeleting")
	logger.Info("restore event: CleanUnusedRestoreClusterJob",
		zap.Uint64("clusterID", event.ClusterID))
	app := container.Global()

	restores, err := app.RestoreRepo.List(ctx, func(qs entity.RestoreQuerySet) entity.RestoreQuerySet {
		return qs.ClusterIDEq(entity.ID(event.ClusterID))
	})
	if err != nil {
		logger.Error("restore event: List Restore",
			zap.Uint64("clusterID", event.ClusterID), zap.Error(err))
		return err
	}
	if len(restores) == 0 {
		return nil
	}
	for _, restore := range restores {
		if r.skipIfDisableRestoreWithWorkflow(restore) {
			logger.Info("restore event: restore.KernelMetrics is nil")
			continue
		}
		if _, err := app.RestoreModelRouter.Cancel(ctx, &domain.CancelRestoreReqV2{
			RestoreID: uint64(restore.ID),
		}); err != nil {
			logger.Error("restore event: Cancel Restore",
				zap.Uint64("clusterID", event.ClusterID), zap.Error(err))
			return err
		}
	}
	return nil
}

func (r *RestoreWithClusterDeleting) skipIfDisableRestoreWithWorkflow(restore entity.Restore) bool {
	return restore.KernelMetrics == nil
}
