// Package telemetry owns the backend's OpenTelemetry wiring. The provider
// bootstrap (exporter selection, propagators, shutdown, Go runtime metrics) is
// shared across the Scrabble services in scrabble/pkg/telemetry; this package is a
// thin backend-flavoured facade over it (the "scrabble-backend" default service
// name) plus the backend-specific gin request-timing middleware (middleware.go),
// which uses the registered global tracer so requests are timed and logged even
// when the exporter is "none".
package telemetry

import (
	"context"

	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"

	pkgtel "scrabble/pkg/telemetry"
)

// Exporter selectors, re-exported from scrabble/pkg/telemetry so the backend's
// config and tests need not import the shared package directly.
const (
	ExporterNone   = pkgtel.ExporterNone
	ExporterStdout = pkgtel.ExporterStdout
	ExporterOTLP   = pkgtel.ExporterOTLP
)

// DefaultServiceName labels traces and metrics when BACKEND_SERVICE_NAME is unset.
const DefaultServiceName = "scrabble-backend"

// Config selects the telemetry providers' service name and exporters. It aliases
// the shared configuration type.
type Config = pkgtel.Config

// Runtime owns the shared OpenTelemetry providers. It aliases the shared runtime
// type, so callers keep using telemetry.Runtime.
type Runtime = pkgtel.Runtime

// DefaultConfig returns the backend's telemetry configuration: the
// "scrabble-backend" service name and both exporters off (so no collector is
// required locally or in CI).
func DefaultConfig() Config {
	return pkgtel.DefaultConfig(DefaultServiceName)
}

// New constructs the telemetry runtime, registers the global providers and the
// W3C propagators, and returns the Runtime. Callers must invoke Runtime.Shutdown
// during process exit.
func New(ctx context.Context, cfg Config) (*Runtime, error) {
	return pkgtel.New(ctx, cfg)
}

// TraceFieldsFromContext returns zap fields identifying the active span, or nil
// when ctx carries no valid span context. Collocated here so callers (the
// request-timing middleware and the access log) do not import the OpenTelemetry
// API directly.
func TraceFieldsFromContext(ctx context.Context) []zap.Field {
	if ctx == nil {
		return nil
	}
	sc := trace.SpanContextFromContext(ctx)
	if !sc.IsValid() {
		return nil
	}
	return []zap.Field{
		zap.String("otel_trace_id", sc.TraceID().String()),
		zap.String("otel_span_id", sc.SpanID().String()),
	}
}
