package blobstor

import (
	"context"

	"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/blobstor/common"
	oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
	"go.uber.org/zap"
)

type StorageIDUpdate interface {
	UpdateStorageID(ctx context.Context, addr oid.Address, storageID []byte) error
}

type ConcurrentWorkersLimiter interface {
	AcquireWorkSlot(ctx context.Context) error
	ReleaseWorkSlot()
}

func (b *BlobStor) Rebuild(ctx context.Context, upd StorageIDUpdate, limiter ConcurrentWorkersLimiter) error {
	var summary common.RebuildRes
	var rErr error
	for _, storage := range b.storage {
		res, err := storage.Storage.Rebuild(ctx, common.RebuildPrm{
			MetaStorage:   upd,
			WorkerLimiter: limiter,
		})
		summary.FilesRemoved += res.FilesRemoved
		summary.ObjectsMoved += res.ObjectsMoved
		if err != nil {
			b.log.Error(logs.BlobstorRebuildFailedToRebuildStorages,
				zap.String("failed_storage_path", storage.Storage.Path()),
				zap.String("failed_storage_type", storage.Storage.Type()),
				zap.Error(err))
			rErr = err
			break
		}
	}
	b.log.Info(logs.BlobstorRebuildRebuildStoragesCompleted,
		zap.Bool("success", rErr == nil),
		zap.Uint64("total_files_removed", summary.FilesRemoved),
		zap.Uint64("total_objects_moved", summary.ObjectsMoved))
	return rErr
}