package log

import (
	"context"
	"fmt"
	"tercul/internal/observability"

	"github.com/rs/zerolog"
)

// Logger is a wrapper around the observability logger.
type Logger struct {
	*observability.Logger
}

// defaultLogger is the global fallback logger.
var defaultLogger = observability.NewLogger("tercul", "development")

// Init re-initializes the default logger. This is useful for applications
// that need to configure the logger with dynamic values from config.
func Init(serviceName, environment string) {
	defaultLogger = observability.NewLogger(serviceName, environment)
}

// FromContext retrieves the request-scoped logger from the context.
// If no logger is found, it returns the default global logger.
func FromContext(ctx context.Context) *Logger {
	// We wrap the observability.Logger in our platform.Logger
	return &Logger{observability.LoggerFromContext(ctx)}
}

// SetLevel sets the global log level.
func SetLevel(level zerolog.Level) {
	zerolog.SetGlobalLevel(level)
}

// Debug logs a message at debug level.
func (l *Logger) Debug(msg string) {
	l.Logger.Debug().Msg(msg)
}

// Info logs a message at info level.
func (l *Logger) Info(msg string) {
	l.Logger.Info().Msg(msg)
}

// Warn logs a message at warn level.
func (l *Logger) Warn(msg string) {
	l.Logger.Warn().Msg(msg)
}

// Error logs a message at error level.
func (l *Logger) Error(err error, msg string) {
	l.Logger.Error().Err(err).Msg(msg)
}

// Fatal logs a message at fatal level and then calls os.Exit(1).
func (l *Logger) Fatal(err error, msg string) {
	l.Logger.Fatal().Err(err).Msg(msg)
}

// With adds a key-value pair to the logger's context.
func (l *Logger) With(key string, value interface{}) *Logger {
	return &Logger{l.Logger.With(key, value)}
}

// Infof logs a formatted message at info level.
func (l *Logger) Infof(format string, v ...interface{}) {
	l.Info(fmt.Sprintf(format, v...))
}

// Errorf logs a formatted message at error level.
func (l *Logger) Errorf(err error, format string, v ...interface{}) {
	l.Error(err, fmt.Sprintf(format, v...))
}

// The following functions use the default logger and are kept for convenience
// in areas where a context is not available.

// Debug logs a message at debug level using the default logger.
func Debug(msg string) {
	defaultLogger.Debug().Msg(msg)
}

// Info logs a message at info level using the default logger.
func Info(msg string) {
	defaultLogger.Info().Msg(msg)
}

// Warn logs a message at warn level using the default logger.
func Warn(msg string) {
	defaultLogger.Warn().Msg(msg)
}

// Error logs a message at error level using the default logger.
func Error(err error, msg string) {
	defaultLogger.Error().Err(err).Msg(msg)
}

// Fatal logs a message at fatal level using the default logger.
func Fatal(err error, msg string) {
	defaultLogger.Fatal().Err(err).Msg(msg)
}