package getsvc

import (
	"context"
	"errors"

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

func (exec *execCtx) processNode(ctx context.Context, info client.NodeInfo) bool {
	exec.log.Debug("processing node...")

	client, ok := exec.remoteClient(info)
	if !ok {
		return true
	}

	obj, err := client.getObject(ctx, exec, info)

	var errSplitInfo *objectSDK.SplitInfoError
	var errRemoved *apistatus.ObjectAlreadyRemoved
	var errOutOfRange *apistatus.ObjectOutOfRange

	switch {
	default:
		var errNotFound apistatus.ObjectNotFound

		exec.status = statusUndefined
		exec.err = errNotFound

		exec.log.Debug("remote call failed",
			zap.String("error", err.Error()),
		)
	case err == nil:
		exec.status = statusOK
		exec.err = nil

		// both object and err are nil only if the original
		// request was forwarded to another node and the object
		// has already been streamed to the requesting party
		if obj != nil {
			exec.collectedObject = obj
			exec.writeCollectedObject(ctx)
		}
	case errors.As(err, &errRemoved):
		exec.status = statusINHUMED
		exec.err = errRemoved
	case errors.As(err, &errOutOfRange):
		exec.status = statusOutOfRange
		exec.err = errOutOfRange
	case errors.As(err, &errSplitInfo):
		exec.status = statusVIRTUAL
		mergeSplitInfo(exec.splitInfo(), errSplitInfo.SplitInfo())
		exec.err = objectSDK.NewSplitInfoError(exec.infoSplit)
	}

	return exec.status != statusUndefined
}