package logger

import (
	"context"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type ctxKey struct{}

const requestIDKey = "request_id"

func WithRequestID(logger *zap.Logger, requestID string) *zap.Logger {
	return logger.With(zap.String(requestIDKey, requestID))
}

func WithContext(logger *zap.Logger, fields map[string]interface{}) *zap.Logger {
	zapFields := make([]zap.Field, 0, len(fields))
	for k, v := range fields {
		zapFields = append(zapFields, zap.Any(k, v))
	}
	return logger.With(zapFields...)
}

func RequestIDFromGinContext(c *gin.Context) zap.Field {
	requestID, exists := c.Get("request_id")
	if !exists {
		return zap.Skip()
	}
	if id, ok := requestID.(string); ok {
		return RequestID(id)
	}
	return zap.Skip()
}

func RequestIDFromContext(ctx context.Context) zap.Field {
	requestID := ctx.Value(ctxKey{})
	if requestID == nil {
		return zap.Skip()
	}
	if id, ok := requestID.(string); ok {
		return RequestID(id)
	}
	return zap.Skip()
}

func ContextWithRequestID(ctx context.Context, requestID string) context.Context {
	return context.WithValue(ctx, ctxKey{}, requestID)
}

func LoggerFromContext(ctx context.Context, baseLogger *zap.Logger) *zap.Logger {
	field := RequestIDFromContext(ctx)
	if field == zap.Skip() {
		return baseLogger
	}
	return baseLogger.With(field)
}
