package oracle

import (
	"strings"

	fxv1 "github.com/tech/sendico/pkg/proto/common/fx/v1"
	moneyv1 "github.com/tech/sendico/pkg/proto/common/money/v1"
	tracev1 "github.com/tech/sendico/pkg/proto/common/trace/v1"
	oraclev1 "github.com/tech/sendico/pkg/proto/oracle/v1"
	"go.uber.org/zap"
)

func quoteRequestFields(req *oraclev1.GetQuoteRequest) []zap.Field {
	if req == nil {
		return nil
	}
	fields := requestMetaFields(req.GetMeta())
	if pair := req.GetPair(); pair != nil {
		if base := strings.TrimSpace(pair.GetBase()); base != "" {
			fields = append(fields, zap.String("pair_base", base))
		}
		if quote := strings.TrimSpace(pair.GetQuote()); quote != "" {
			fields = append(fields, zap.String("pair_quote", quote))
		}
	}
	if side := req.GetSide(); side != fxv1.Side_SIDE_UNSPECIFIED {
		fields = append(fields, zap.String("side", side.String()))
	}
	if req.GetFirm() {
		fields = append(fields, zap.Bool("firm", req.GetFirm()))
	}
	if ttl := req.GetTtlMs(); ttl > 0 {
		fields = append(fields, zap.Int64("ttl_ms", ttl))
	}
	if maxAge := req.GetMaxAgeMs(); maxAge > 0 {
		fields = append(fields, zap.Int32("max_age_ms", maxAge))
	}
	if provider := strings.TrimSpace(req.GetPreferredProvider()); provider != "" {
		fields = append(fields, zap.String("preferred_provider", provider))
	}
	fields = append(fields, moneyFields("base_amount", req.GetBaseAmount())...)
	fields = append(fields, moneyFields("quote_amount", req.GetQuoteAmount())...)
	return fields
}

func requestMetaFields(meta *oraclev1.RequestMeta) []zap.Field {
	if meta == nil {
		return nil
	}
	fields := make([]zap.Field, 0, 4)
	if org := strings.TrimSpace(meta.GetOrganizationRef()); org != "" {
		fields = append(fields, zap.String("organization_ref", org))
	}
	if tenant := strings.TrimSpace(meta.GetTenantRef()); tenant != "" {
		fields = append(fields, zap.String("tenant_ref", tenant))
	}
	fields = append(fields, traceFields(meta.GetTrace())...)
	return fields
}

func moneyFields(prefix string, money *moneyv1.Money) []zap.Field {
	if money == nil {
		return nil
	}
	fields := make([]zap.Field, 0, 2)
	if amt := strings.TrimSpace(money.GetAmount()); amt != "" {
		fields = append(fields, zap.String(prefix, amt))
	}
	if ccy := strings.TrimSpace(money.GetCurrency()); ccy != "" {
		fields = append(fields, zap.String(prefix+"_currency", ccy))
	}
	return fields
}

func traceFields(trace *tracev1.TraceContext) []zap.Field {
	if trace == nil {
		return nil
	}
	fields := make([]zap.Field, 0, 3)
	if ref := strings.TrimSpace(trace.GetTraceRef()); ref != "" {
		fields = append(fields, zap.String("trace_ref", ref))
	}
	if idem := strings.TrimSpace(trace.GetIdempotencyKey()); idem != "" {
		fields = append(fields, zap.String("idempotency_key", idem))
	}
	if req := strings.TrimSpace(trace.GetRequestRef()); req != "" {
		fields = append(fields, zap.String("request_ref", req))
	}
	return fields
}
