package engine

import (
	"context"
	"errors"

	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/shard"
	"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
	apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
	objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
	"go.uber.org/zap"
)

// exists return in the first value true if object exists.
// Second return value marks is parent object locked.
func (e *StorageEngine) exists(ctx context.Context, shPrm shard.ExistsPrm) (bool, bool, error) {
	alreadyRemoved := false
	exists := false
	locked := false

	e.iterateOverSortedShards(shPrm.Address, func(_ int, sh hashedShard) (stop bool) {
		res, err := sh.Exists(ctx, shPrm)
		if err != nil {
			if client.IsErrObjectAlreadyRemoved(err) {
				alreadyRemoved = true

				return true
			}

			var siErr *objectSDK.SplitInfoError
			if errors.As(err, &siErr) {
				return true
			}

			if shard.IsErrObjectExpired(err) {
				return true
			}

			if !client.IsErrObjectNotFound(err) {
				e.reportShardError(sh, "could not check existence of object in shard", err, zap.Stringer("address", shPrm.Address))
			}
			return false
		}

		if !exists {
			exists = res.Exists()
		}
		if !locked {
			locked = res.Locked()
		}

		return false
	})

	if alreadyRemoved {
		return false, false, new(apistatus.ObjectAlreadyRemoved)
	}

	return exists, locked, nil
}