package backend

import (
	"context"

	"github.com/tidbcloud/chaos-svc/idl/pbgen/proto/chaos"
	"github.com/tidbcloud/chaos-svc/pkg/domain/repo"
	"github.com/tidbcloud/chaos-svc/pkg/domain/service/backend"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/pkgv2/db"
	"github.com/tidbcloud/pkgv2/log"
)

type SyncBackendFromInfraSvc struct {
	trans                   db.TransProvider
	backendRepo             repo.BackendRepo
	syncBackendFromInfraSvc backend.SyncBackendFromInfraSvc
}

func NewSyncBackendFromInfraSvc(
	trans db.TransProvider,
	backendRepo repo.BackendRepo,
	syncBackendFromInfraSvc backend.SyncBackendFromInfraSvc,
) *SyncBackendFromInfraSvc {
	return &SyncBackendFromInfraSvc{
		trans:                   trans,
		backendRepo:             backendRepo,
		syncBackendFromInfraSvc: syncBackendFromInfraSvc,
	}
}

func (svc *SyncBackendFromInfraSvc) Execute(ctx context.Context) bizerr.BizError {
	logger := log.WithContextL(ctx).Sugar()

	backends, err := svc.backendRepo.QueryBackends(ctx, repo.BackendFilter{
		Statuses: []chaos.ChaosBackendStatus{
			chaos.ChaosBackendStatus_CHAOS_BACKEND_STATUS_INSTALLING,
			chaos.ChaosBackendStatus_CHAOS_BACKEND_STATUS_UNINSTALLING,
		},
	})
	if err != nil {
		return err
	}

	succeedNum := 0
	for _, each := range backends {
		if err := svc.trans.Transaction(ctx, func(ctx context.Context) error {
			return svc.syncBackendFromInfraSvc.Execute(ctx, each.ProjectID, each.NetworkName)
		}); err != nil {
			logger.Warnf("sync chaos backend from infra failed, projectID=%d, networkName=%s: %s", each.ProjectID, each.NetworkName, err)
			continue
		}

		succeedNum += 1
	}

	logger.Infof("sync chaos backend done, succ: %d/%d", succeedNum, len(backends))
	return nil
}
