package tracing

import (
	"context"
	"fmt"
	"time"
)

// ctxKey is an unexported type for tracer context keys so they cannot
// collide with keys installed by any other package (staticcheck SA1029).
type ctxKey string

const (
	ctxKeyTraceID ctxKey = "trace_id"
	ctxKeySpanID  ctxKey = "span_id"
)

// Tracer provides distributed tracing
type Tracer struct {
	serviceName string
}

// NewTracer creates a new tracer
func NewTracer(serviceName string) *Tracer {
	return &Tracer{serviceName: serviceName}
}

// Span represents a trace span
type Span struct {
	TraceID    string
	SpanID     string
	ParentID   string
	Name       string
	StartTime  time.Time
	EndTime    time.Time
	Tags       map[string]string
	Logs       []LogEntry
}

// LogEntry represents a log entry in a span
type LogEntry struct {
	Timestamp time.Time
	Fields    map[string]interface{}
}

// StartSpan starts a new span
func (t *Tracer) StartSpan(ctx context.Context, name string) (*Span, context.Context) {
	traceID := generateID()
	spanID := generateID()

	span := &Span{
		TraceID:   traceID,
		SpanID:    spanID,
		Name:      name,
		StartTime: time.Now(),
		Tags:      make(map[string]string),
		Logs:      []LogEntry{},
	}

	ctx = context.WithValue(ctx, ctxKeyTraceID, traceID)
	ctx = context.WithValue(ctx, ctxKeySpanID, spanID)

	return span, ctx
}

// Finish finishes a span
func (s *Span) Finish() {
	s.EndTime = time.Now()
	// In production, this would send span to tracing backend
}

// SetTag sets a tag on the span
func (s *Span) SetTag(key, value string) {
	s.Tags[key] = value
}

// Log adds a log entry to the span
func (s *Span) Log(fields map[string]interface{}) {
	s.Logs = append(s.Logs, LogEntry{
		Timestamp: time.Now(),
		Fields:    fields,
	})
}

// generateID generates a random ID
func generateID() string {
	return fmt.Sprintf("%x", time.Now().UnixNano())
}

