package observability

import (
	"context"
	"log/slog"
	"net/url"
	"time"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
	"go.opentelemetry.io/otel/propagation"
	"go.opentelemetry.io/otel/sdk/resource"
	sdktrace "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)

// InitTracer 初始化 OpenTelemetry tracer（W6 裁决：资源属性补全）。
//
// 资源属性包含：service.name / service.version / deployment.environment / host.name。
// endpoint 为 "http://host:port" 格式（如 "http://localhost:4318"）；
// 为空时跳过初始化（tracing disabled）。
//
// 返回 shutdown 函数，应在服务退出时调用以 flush 待发送 span。
func InitTracer(serviceName, endpoint, env, version, hostName string) func() {
	if endpoint == "" {
		slog.Info("OTEL endpoint not set, tracing disabled")
		return func() {}
	}

	u, err := url.Parse(endpoint)
	if err != nil || u.Host == "" {
		slog.Warn("invalid OTEL endpoint, tracing disabled", "endpoint", endpoint)
		return func() {}
	}

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	exporter, err := otlptracehttp.New(ctx,
		otlptracehttp.WithEndpoint(u.Host),
		otlptracehttp.WithInsecure(),
	)
	if err != nil {
		slog.Error("failed to create OTLP exporter, tracing disabled", "error", err)
		return func() {}
	}

	// W6 裁决：资源属性补全（service.name + version + env + host）
	res, err := resource.New(ctx,
		resource.WithAttributes(
			semconv.ServiceName(serviceName),
			attribute.String("service.version", version),
			attribute.String("deployment.environment", env),
			attribute.String("host.name", hostName),
		),
	)
	if err != nil {
		slog.Error("failed to create resource", "error", err)
		return func() {}
	}

	tp := sdktrace.NewTracerProvider(
		sdktrace.WithBatcher(exporter),
		sdktrace.WithResource(res),
	)
	otel.SetTracerProvider(tp)
	otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
		propagation.TraceContext{},
		propagation.Baggage{},
	))

	slog.Info("OpenTelemetry tracer initialized",
		"service", serviceName,
		"endpoint", u.Host,
		"env", env,
		"version", version,
		"host", hostName,
	)
	return func() {
		shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		if err := tp.Shutdown(shutdownCtx); err != nil {
			slog.Error("failed to shutdown tracer", "error", err)
		}
	}
}
