package transfer

import (
	"context"
	"strings"

	"github.com/tech/sendico/gateway/tron/storage/model"
	"github.com/tech/sendico/pkg/merrors"
	chainv1 "github.com/tech/sendico/pkg/proto/gateway/chain/v1"
	"go.uber.org/zap"
)

func resolveDestination(ctx context.Context, deps Deps, dest *chainv1.TransferDestination, source *model.ManagedWallet) (model.TransferDestination, error) {
	if dest == nil {
		return model.TransferDestination{}, merrors.InvalidArgument("destination is required")
	}
	managedRef := strings.TrimSpace(dest.GetManagedWalletRef())
	external := strings.TrimSpace(dest.GetExternalAddress())
	if managedRef != "" && external != "" {
		deps.Logger.Warn("Both managed and external destination provided")
		return model.TransferDestination{}, merrors.InvalidArgument("destination must be managed_wallet_ref or external_address")
	}
	if managedRef != "" {
		wallet, err := deps.Storage.Wallets().Get(ctx, managedRef)
		if err != nil {
			deps.Logger.Warn("Destination wallet lookup failed", zap.Error(err), zap.String("managed_wallet_ref", managedRef))
			return model.TransferDestination{}, err
		}
		if !strings.EqualFold(wallet.Network, source.Network) {
			deps.Logger.Warn("Destination wallet network mismatch", zap.String("source_network", source.Network), zap.String("dest_network", wallet.Network))
			return model.TransferDestination{}, merrors.InvalidArgument("destination wallet network mismatch")
		}
		if strings.TrimSpace(wallet.DepositAddress) == "" {
			deps.Logger.Warn("Destination wallet missing deposit address", zap.String("managed_wallet_ref", managedRef))
			return model.TransferDestination{}, merrors.InvalidArgument("destination wallet missing deposit address")
		}
		return model.TransferDestination{
			ManagedWalletRef: wallet.WalletRef,
			Memo:             strings.TrimSpace(dest.GetMemo()),
		}, nil
	}
	if external == "" {
		deps.Logger.Warn("Destination external address missing")
		return model.TransferDestination{}, merrors.InvalidArgument("destination is required")
	}
	if deps.Drivers == nil {
		deps.Logger.Warn("Chain drivers missing", zap.String("network", source.Network))
		return model.TransferDestination{}, merrors.Internal("chain drivers not configured")
	}
	chainDriver, err := deps.Drivers.Driver(source.Network)
	if err != nil {
		deps.Logger.Warn("Unsupported chain driver", zap.String("network", source.Network), zap.Error(err))
		return model.TransferDestination{}, merrors.InvalidArgument("unsupported chain for wallet")
	}
	normalized, err := chainDriver.NormalizeAddress(external)
	if err != nil {
		deps.Logger.Warn("Invalid external address", zap.Error(err))
		return model.TransferDestination{}, err
	}
	return model.TransferDestination{
		ExternalAddress:         normalized,
		ExternalAddressOriginal: external,
		Memo:                    strings.TrimSpace(dest.GetMemo()),
	}, nil
}
