package fees

import (
	"strings"
	"time"

	feesv1 "github.com/tech/sendico/pkg/proto/billing/fees/v1"
	tracev1 "github.com/tech/sendico/pkg/proto/common/trace/v1"
	"go.uber.org/zap"
)

func requestLogFields(meta *feesv1.RequestMeta, intent *feesv1.Intent) []zap.Field {
	fields := logFieldsFromRequestMeta(meta)
	fields = append(fields, logFieldsFromIntent(intent)...)

	return fields
}

func logFieldsFromRequestMeta(meta *feesv1.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))
	}

	fields = append(fields, logFieldsFromTrace(meta.GetTrace())...)

	return fields
}

func logFieldsFromIntent(intent *feesv1.Intent) []zap.Field {
	if intent == nil {
		return nil
	}

	fields := make([]zap.Field, 0, 5)
	if trigger := intent.GetTrigger(); trigger != feesv1.Trigger_TRIGGER_UNSPECIFIED {
		fields = append(fields, zap.String("trigger", trigger.String()))
	}

	if base := intent.GetBaseAmount(); base != nil {
		if amount := strings.TrimSpace(base.GetAmount()); amount != "" {
			fields = append(fields, zap.String("base_amount", amount))
		}

		if currency := strings.TrimSpace(base.GetCurrency()); currency != "" {
			fields = append(fields, zap.String("base_currency", currency))
		}
	}

	if booked := intent.GetBookedAt(); booked != nil && booked.IsValid() {
		fields = append(fields, zap.Time("booked_at", booked.AsTime()))
	}

	if attrs := intent.GetAttributes(); len(attrs) > 0 {
		fields = append(fields, zap.Int("attributes_count", len(attrs)))
	}

	return fields
}

func logFieldsFromTrace(trace *tracev1.TraceContext) []zap.Field {
	if trace == nil {
		return nil
	}

	fields := make([]zap.Field, 0, 3)
	if reqRef := strings.TrimSpace(trace.GetRequestRef()); reqRef != "" {
		fields = append(fields, zap.String("request_ref", reqRef))
	}

	if idem := strings.TrimSpace(trace.GetIdempotencyKey()); idem != "" {
		fields = append(fields, zap.String("idempotency_key", idem))
	}

	if traceRef := strings.TrimSpace(trace.GetTraceRef()); traceRef != "" {
		fields = append(fields, zap.String("trace_ref", traceRef))
	}

	return fields
}

func logFieldsFromTokenPayload(payload *feeQuoteTokenPayload) []zap.Field {
	if payload == nil {
		return nil
	}

	fields := make([]zap.Field, 0, 6)
	if org := strings.TrimSpace(payload.OrganizationRef); org != "" {
		fields = append(fields, zap.String("organization_ref", org))
	}

	if payload.ExpiresAtUnixMs > 0 {
		fields = append(fields,
			zap.Int64("expires_at_unix_ms", payload.ExpiresAtUnixMs),
			zap.Time("expires_at", time.UnixMilli(payload.ExpiresAtUnixMs)))
	}

	fields = append(fields, logFieldsFromIntent(payload.Intent)...)
	fields = append(fields, logFieldsFromTrace(payload.Trace)...)

	return fields
}
