package transfer

import (
	"context"
	"strings"

	"github.com/tech/sendico/gateway/tron/shared"
	"github.com/tech/sendico/gateway/tron/storage/model"
	"github.com/tech/sendico/pkg/api/routers/gsresponse"
	"github.com/tech/sendico/pkg/mservice"
	paginationv1 "github.com/tech/sendico/pkg/proto/common/pagination/v1"
	chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
	"go.uber.org/zap"
)

type listTransfersCommand struct {
	deps Deps
}

func NewListTransfers(deps Deps) *listTransfersCommand {
	return &listTransfersCommand{deps: deps}
}

func (c *listTransfersCommand) Execute(ctx context.Context, req *chainv1.ListTransfersRequest) gsresponse.Responder[chainv1.ListTransfersResponse] {
	if err := c.deps.EnsureRepository(ctx); err != nil {
		c.deps.Logger.Warn("Repository unavailable", zap.Error(err))
		return gsresponse.Unavailable[chainv1.ListTransfersResponse](c.deps.Logger, mservice.ChainGateway, err)
	}
	filter := model.TransferFilter{}
	if req != nil {
		filter.SourceWalletRef = strings.TrimSpace(req.GetSourceWalletRef())
		filter.DestinationWalletRef = strings.TrimSpace(req.GetDestinationWalletRef())
		if status := shared.TransferStatusToModel(req.GetStatus()); status != "" {
			filter.Status = status
		}
		if page := req.GetPage(); page != nil {
			filter.Cursor = strings.TrimSpace(page.GetCursor())
			filter.Limit = page.GetLimit()
		}
	}

	result, err := c.deps.Storage.Transfers().List(ctx, filter)
	if err != nil {
		c.deps.Logger.Warn("Storage list failed", zap.Error(err))
		return gsresponse.Auto[chainv1.ListTransfersResponse](c.deps.Logger, mservice.ChainGateway, err)
	}

	protoTransfers := make([]*chainv1.Transfer, 0, len(result.Items))
	for _, transfer := range result.Items {
		protoTransfers = append(protoTransfers, toProtoTransfer(transfer))
	}

	resp := &chainv1.ListTransfersResponse{
		Transfers: protoTransfers,
		Page:      &paginationv1.CursorPageResponse{NextCursor: result.NextCursor},
	}
	return gsresponse.Success(resp)
}
