package log

import (
	"context"
	"github.com/pingcap/log"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"
)

// WithContextL returns the global Logger, and add some filed which get from ctx
func WithContextL(ctx context.Context) *zap.Logger {
	return log.L().With(TraceIDFromContext(ctx)...)
}

// WithContextS returns the global SugaredLogger, and add some filed which get from ctx
func WithContextS(ctx context.Context) *zap.SugaredLogger {
	return log.L().With(TraceIDFromContext(ctx)...).Sugar()
}

func AppendCtxFields(ctx context.Context, logger *zap.Logger) *zap.Logger {
	return logger.With(TraceIDFromContext(ctx)...)
}

func TraceIDFromContext(ctx context.Context) []zap.Field {
	spanCtx := trace.SpanContextFromContext(ctx)
	var fields []zap.Field
	if spanCtx.HasTraceID() {
		fields = append(fields, zap.String(traceId, spanCtx.TraceID().String()))
	}
	span := trace.SpanFromContext(ctx)

	if span != nil {
		if spanTracer, ok := span.(interface{ Attributes() []attribute.KeyValue }); ok {
			for _, attr := range spanTracer.Attributes() {
				switch attr.Key {
				case attributeModule:
					fields = append(fields, zap.String(attributeModule, attr.Value.AsString()))
				case attributeOperation:
					fields = append(fields, zap.String(attributeOperation, attr.Value.AsString()))
				}
			}
		}
	}

	if v := ctx.Value(attributeModule); v != nil {
		if s, ok := v.(string); ok && s != "" {
			fields = append(fields, zap.String(attributeModule, s))
		}
	}
	if v := ctx.Value(attributeOperation); v != nil {
		if s, ok := v.(string); ok && s != "" {
			fields = append(fields, zap.String(attributeOperation, s))
		}
	}

	return fields
}
