package transfer

import (
	"context"
	"errors"
	"strings"

	"github.com/tech/sendico/pkg/api/routers/gsresponse"
	"github.com/tech/sendico/pkg/merrors"
	"github.com/tech/sendico/pkg/mservice"
	chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
	"go.uber.org/zap"
)

type getTransferCommand struct {
	deps Deps
}

func NewGetTransfer(deps Deps) *getTransferCommand {
	return &getTransferCommand{deps: deps}
}

func (c *getTransferCommand) Execute(ctx context.Context, req *chainv1.GetTransferRequest) gsresponse.Responder[chainv1.GetTransferResponse] {
	if err := c.deps.EnsureRepository(ctx); err != nil {
		c.deps.Logger.Warn("Repository unavailable", zap.Error(err))
		return gsresponse.Unavailable[chainv1.GetTransferResponse](c.deps.Logger, mservice.ChainGateway, err)
	}
	if req == nil {
		c.deps.Logger.Warn("Nil request")
		return gsresponse.InvalidArgument[chainv1.GetTransferResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("nil request"))
	}
	transferRef := strings.TrimSpace(req.GetTransferRef())
	if transferRef == "" {
		c.deps.Logger.Warn("Transfer_ref missing")
		return gsresponse.InvalidArgument[chainv1.GetTransferResponse](c.deps.Logger, mservice.ChainGateway, merrors.InvalidArgument("transfer_ref is required"))
	}
	transfer, err := c.deps.Storage.Transfers().Get(ctx, transferRef)
	if err != nil {
		if errors.Is(err, merrors.ErrNoData) {
			c.deps.Logger.Warn("Not found", zap.String("transfer_ref", transferRef))
			return gsresponse.NotFound[chainv1.GetTransferResponse](c.deps.Logger, mservice.ChainGateway, err)
		}
		c.deps.Logger.Warn("Storage get failed", zap.Error(err), zap.String("transfer_ref", transferRef))
		return gsresponse.Auto[chainv1.GetTransferResponse](c.deps.Logger, mservice.ChainGateway, err)
	}
	return gsresponse.Success(&chainv1.GetTransferResponse{Transfer: toProtoTransfer(transfer)})
}
