package gc

import (
	"context"

	"github.com/pingcap/errors"
	"github.com/pingcap/log"
	regionalpb "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"
	"github.com/tidbcloud/ticdc-service/pkg/cloud"
	"github.com/tidbcloud/ticdc-service/pkg/regionalservice"
	"go.uber.org/zap"
)

type dataplaneGCWorker struct {
	appboxCli    regionalservice.Client
	gcExecutor   cloud.GCExecutor
	appboxLister cloud.AppboxLister
}

func NewDataPlaneGCWorker(
	appboxCli regionalservice.Client,
	gcExecutor cloud.GCExecutor,
	appboxLister cloud.AppboxLister) Worker {
	return &dataplaneGCWorker{
		appboxCli:    appboxCli,
		gcExecutor:   gcExecutor,
		appboxLister: appboxLister,
	}
}

func (g *dataplaneGCWorker) Run(ctx context.Context) error {
	appboxsIDs, err := g.appboxLister.ListAppbox(ctx)
	if err != nil {
		return errors.Trace(err)
	}

	log.Info("list appbox successfully", zap.Int("appboxs", len(appboxsIDs)))
	for _, appboxID := range appboxsIDs {
		appbox, err := g.appboxCli.GetAPPBoxByID(ctx, appboxID)
		if err != nil {
			log.Warn("get appbox failed",
				zap.String("appboxID", appboxID), zap.Error(err))
			continue
		}
		if !shouldGCAppBox(appbox) {
			continue
		}

		log.Info("appbox is in deleting status, gc the sub resources",
			zap.String("appboxID", appboxID))
		if err := g.gcExecutor.OnAppboxDeleting(ctx, appboxID); err != nil {
			log.Warn("failed to delete appbox sub resources",
				zap.String("appboxID", appboxID), zap.Error(err))
		}
	}
	return nil
}

// appbox will remain regionalpb.APPBox_DELETING status until all sub resource is deleted
func shouldGCAppBox(appbox *regionalpb.APPBox) bool {
	return appbox.Status == regionalpb.APPBox_DELETING
}
