package quote_computation_service

import (
	"strings"

	qshared "github.com/tech/sendico/payments/quotation/internal/shared"
	"github.com/tech/sendico/payments/storage/model"
	paymenttypes "github.com/tech/sendico/pkg/payments/types"
	moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
)

func cloneProtoMoney(src *moneyv1.Money) *moneyv1.Money {
	return qshared.CloneProtoMoneyTrim(src)
}

func protoMoneyFromModel(src *paymenttypes.Money) *moneyv1.Money {
	if src == nil {
		return nil
	}
	return &moneyv1.Money{
		Amount:   strings.TrimSpace(src.GetAmount()),
		Currency: strings.ToUpper(strings.TrimSpace(src.GetCurrency())),
	}
}

func cloneStringMap(src map[string]string) map[string]string {
	if len(src) == 0 {
		return nil
	}
	out := make(map[string]string, len(src))
	for k, v := range src {
		key := strings.TrimSpace(k)
		if key == "" {
			continue
		}
		out[key] = strings.TrimSpace(v)
	}
	if len(out) == 0 {
		return nil
	}
	return out
}

func cloneAsset(src *paymenttypes.Asset) *paymenttypes.Asset {
	if src == nil {
		return nil
	}
	return &paymenttypes.Asset{
		Chain:           strings.TrimSpace(src.Chain),
		TokenSymbol:     strings.TrimSpace(src.TokenSymbol),
		ContractAddress: strings.TrimSpace(src.ContractAddress),
	}
}

func cloneModelMoney(src *paymenttypes.Money) *paymenttypes.Money {
	return qshared.CloneModelMoneyTrimUpperCurrency(src)
}

func clonePaymentIntent(src model.PaymentIntent) model.PaymentIntent {
	out := model.PaymentIntent{
		Ref:                strings.TrimSpace(src.Ref),
		Kind:               src.Kind,
		Source:             clonePaymentEndpoint(src.Source),
		Destination:        clonePaymentEndpoint(src.Destination),
		Amount:             cloneModelMoney(src.Amount),
		RequiresFX:         src.RequiresFX,
		FX:                 nil,
		FeePolicy:          src.FeePolicy,
		SettlementMode:     src.SettlementMode,
		FeeTreatment:       src.FeeTreatment,
		SettlementCurrency: strings.ToUpper(strings.TrimSpace(src.SettlementCurrency)),
		Attributes:         cloneStringMap(src.Attributes),
		Customer:           src.Customer,
	}
	if src.FX != nil {
		fx := *src.FX
		out.FX = &fx
	}
	return out
}

func clonePaymentEndpoint(src model.PaymentEndpoint) model.PaymentEndpoint {
	out := model.PaymentEndpoint{
		Type:          src.Type,
		InstanceID:    strings.TrimSpace(src.InstanceID),
		Metadata:      nil,
		Ledger:        nil,
		ManagedWallet: nil,
		ExternalChain: nil,
		Card:          nil,
	}
	if src.Ledger != nil {
		out.Ledger = &model.LedgerEndpoint{
			LedgerAccountRef:       strings.TrimSpace(src.Ledger.LedgerAccountRef),
			ContraLedgerAccountRef: strings.TrimSpace(src.Ledger.ContraLedgerAccountRef),
		}
	}
	if src.ManagedWallet != nil {
		out.ManagedWallet = &model.ManagedWalletEndpoint{
			ManagedWalletRef: strings.TrimSpace(src.ManagedWallet.ManagedWalletRef),
			Asset:            cloneAsset(src.ManagedWallet.Asset),
		}
	}
	if src.ExternalChain != nil {
		out.ExternalChain = &model.ExternalChainEndpoint{
			Asset:   cloneAsset(src.ExternalChain.Asset),
			Address: strings.TrimSpace(src.ExternalChain.Address),
			Memo:    strings.TrimSpace(src.ExternalChain.Memo),
		}
	}
	if src.Card != nil {
		out.Card = &model.CardEndpoint{
			Pan:               strings.TrimSpace(src.Card.Pan),
			Token:             strings.TrimSpace(src.Card.Token),
			Cardholder:        strings.TrimSpace(src.Card.Cardholder),
			CardholderSurname: strings.TrimSpace(src.Card.CardholderSurname),
			ExpMonth:          src.Card.ExpMonth,
			ExpYear:           src.Card.ExpYear,
			Country:           strings.TrimSpace(src.Card.Country),
			MaskedPan:         strings.TrimSpace(src.Card.MaskedPan),
		}
	}
	if len(src.Metadata) > 0 {
		out.Metadata = cloneStringMap(src.Metadata)
	}
	return out
}

func lookupAttr(attrs map[string]string, keys ...string) string {
	if len(attrs) == 0 {
		return ""
	}
	for _, key := range keys {
		if key == "" {
			continue
		}
		if val := strings.TrimSpace(attrs[key]); val != "" {
			return val
		}
	}
	return ""
}

func firstNonEmpty(values ...string) string {
	for _, value := range values {
		if strings.TrimSpace(value) != "" {
			return strings.TrimSpace(value)
		}
	}
	return ""
}

func normalizeGatewayKey(value string) string {
	return strings.ToLower(strings.TrimSpace(value))
}
