package quote_computation_service

import (
	"strings"

	"github.com/tech/sendico/payments/storage/model"
	paymentv1 "github.com/tech/sendico/pkg/proto/common/payment/v1"
	quotationv2 "github.com/tech/sendico/pkg/proto/payments/quotation/v2"
)

func buildRouteSettlement(
	intent model.PaymentIntent,
	network string,
	hops []*quotationv2.RouteHop,
) *quotationv2.RouteSettlement {
	modelValue := strings.ToLower(strings.TrimSpace(settlementModelString(intent.SettlementMode)))
	asset := buildRouteSettlementAsset(intent, network, hops)
	if asset == nil && modelValue == "" {
		return nil
	}
	return &quotationv2.RouteSettlement{
		Asset: asset,
		Model: modelValue,
	}
}

func buildRouteSettlementAsset(
	intent model.PaymentIntent,
	network string,
	hops []*quotationv2.RouteHop,
) *paymentv1.ChainAsset {
	chain, token, contract := settlementAssetFromIntent(intent)

	if token == "" {
		token = normalizeAsset(intent.SettlementCurrency)
	}
	if token == "" && intent.Amount != nil {
		token = normalizeAsset(intent.Amount.GetCurrency())
	}
	if chain == "" {
		chain = normalizeAsset(firstNonEmpty(network, routeNetworkFromHops(hops)))
	}
	if chain == "" && token == "" && contract == "" {
		return nil
	}

	asset := &paymentv1.ChainAsset{
		Key: &paymentv1.ChainAssetKey{
			Chain:       chain,
			TokenSymbol: token,
		},
	}
	if contract != "" {
		asset.ContractAddress = &contract
	}
	return asset
}

func settlementAssetFromIntent(intent model.PaymentIntent) (chain, token, contract string) {
	candidates := []*model.PaymentEndpoint{
		&intent.Source,
		&intent.Destination,
	}
	for _, endpoint := range candidates {
		if endpoint == nil {
			continue
		}
		if endpoint.ManagedWallet != nil && endpoint.ManagedWallet.Asset != nil {
			return normalizedAssetFields(endpoint.ManagedWallet.Asset.Chain, endpoint.ManagedWallet.Asset.TokenSymbol, endpoint.ManagedWallet.Asset.ContractAddress)
		}
		if endpoint.ExternalChain != nil && endpoint.ExternalChain.Asset != nil {
			return normalizedAssetFields(endpoint.ExternalChain.Asset.Chain, endpoint.ExternalChain.Asset.TokenSymbol, endpoint.ExternalChain.Asset.ContractAddress)
		}
	}
	return "", "", ""
}

func normalizedAssetFields(chain, token, contract string) (string, string, string) {
	return normalizeAsset(chain), normalizeAsset(token), strings.TrimSpace(contract)
}

func routeNetworkFromHops(hops []*quotationv2.RouteHop) string {
	for _, hop := range hops {
		if hop == nil {
			continue
		}
		network := strings.TrimSpace(hop.GetNetwork())
		if network != "" {
			return network
		}
	}
	return ""
}
