package commands

import (
	"context"

	"github.com/tech/sendico/gateway/tron/internal/service/gateway/commands/transfer"
	"github.com/tech/sendico/gateway/tron/internal/service/gateway/commands/wallet"
	"github.com/tech/sendico/pkg/api/routers/gsresponse"
	chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
)

type Unary[TReq any, TResp any] interface {
	Execute(context.Context, *TReq) gsresponse.Responder[TResp]
}

type Registry struct {
	CreateManagedWallet Unary[chainv1.CreateManagedWalletRequest, chainv1.CreateManagedWalletResponse]
	GetManagedWallet    Unary[chainv1.GetManagedWalletRequest, chainv1.GetManagedWalletResponse]
	ListManagedWallets  Unary[chainv1.ListManagedWalletsRequest, chainv1.ListManagedWalletsResponse]
	GetWalletBalance    Unary[chainv1.GetWalletBalanceRequest, chainv1.GetWalletBalanceResponse]

	SubmitTransfer   Unary[chainv1.SubmitTransferRequest, chainv1.SubmitTransferResponse]
	GetTransfer      Unary[chainv1.GetTransferRequest, chainv1.GetTransferResponse]
	ListTransfers    Unary[chainv1.ListTransfersRequest, chainv1.ListTransfersResponse]
	EstimateTransfer Unary[chainv1.EstimateTransferFeeRequest, chainv1.EstimateTransferFeeResponse]
	ComputeGasTopUp  Unary[chainv1.ComputeGasTopUpRequest, chainv1.ComputeGasTopUpResponse]
	EnsureGasTopUp   Unary[chainv1.EnsureGasTopUpRequest, chainv1.EnsureGasTopUpResponse]
}

type RegistryDeps struct {
	Wallet   wallet.Deps
	Transfer transfer.Deps
}

func NewRegistry(deps RegistryDeps) Registry {
	return Registry{
		CreateManagedWallet: wallet.NewCreateManagedWallet(deps.Wallet.WithLogger("wallet.create")),
		GetManagedWallet:    wallet.NewGetManagedWallet(deps.Wallet.WithLogger("wallet.get")),
		ListManagedWallets:  wallet.NewListManagedWallets(deps.Wallet.WithLogger("wallet.list")),
		GetWalletBalance:    wallet.NewGetWalletBalance(deps.Wallet.WithLogger("wallet.balance")),
		SubmitTransfer:      transfer.NewSubmitTransfer(deps.Transfer.WithLogger("transfer.submit")),
		GetTransfer:         transfer.NewGetTransfer(deps.Transfer.WithLogger("transfer.get")),
		ListTransfers:       transfer.NewListTransfers(deps.Transfer.WithLogger("transfer.list")),
		EstimateTransfer:    transfer.NewEstimateTransfer(deps.Transfer.WithLogger("transfer.estimate_fee")),
		ComputeGasTopUp:     transfer.NewComputeGasTopUp(deps.Transfer.WithLogger("gas_topup.compute")),
		EnsureGasTopUp:      transfer.NewEnsureGasTopUp(deps.Transfer.WithLogger("gas_topup.ensure")),
	}
}
