package logger

import (
	"net/http"
	"os"
	"time"

	"github.com/sirupsen/logrus"
)

var (
	// Log is the global logger instance
	Log *logrus.Logger
)

// Fields type, used to pass to functions like WithFields.
type Fields = logrus.Fields

// Initialize sets up the logger with the specified log level
func Initialize(level string) {
	Log = logrus.New()
	Log.SetOutput(os.Stdout)
	Log.SetFormatter(&logrus.JSONFormatter{
		TimestampFormat: "2006-01-02T15:04:05.000Z07:00",
	})

	// Set log level based on the provided string
	switch level {
	case "debug":
		Log.SetLevel(logrus.DebugLevel)
	case "info":
		Log.SetLevel(logrus.InfoLevel)
	case "warn":
		Log.SetLevel(logrus.WarnLevel)
	case "error":
		Log.SetLevel(logrus.ErrorLevel)
	default:
		Log.SetLevel(logrus.InfoLevel)
	}
}

// Debug logs a message at level Debug
func Debug(args ...interface{}) {
	if Log == nil {
		Initialize("info")
	}
	Log.Debug(args...)
}

// Info logs a message at level Info
func Info(args ...interface{}) {
	if Log == nil {
		Initialize("info")
	}
	Log.Info(args...)
}

// Warn logs a message at level Warn
func Warn(args ...interface{}) {
	if Log == nil {
		Initialize("info")
	}
	Log.Warn(args...)
}

// Error logs a message at level Error
func Error(args ...interface{}) {
	if Log == nil {
		Initialize("info")
	}
	Log.Error(args...)
}

// Fatal logs a message at level Fatal then the process will exit with status set to 1
func Fatal(args ...interface{}) {
	if Log == nil {
		Initialize("info")
	}
	Log.Fatal(args...)
}

// WithFields creates an entry from the standard logger and adds multiple fields
func WithFields(fields Fields) *logrus.Entry {
	if Log == nil {
		Initialize("info")
	}
	return Log.WithFields(fields)
}

// HTTPMiddleware logs HTTP requests
func HTTPMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()

		// Create a response writer wrapper to capture the status code
		rw := &responseWriter{
			ResponseWriter: w,
			statusCode:     http.StatusOK, // Default status code
		}

		// Process the request
		next.ServeHTTP(rw, r)

		// Log the request details
		WithFields(Fields{
			"method":     r.Method,
			"path":       r.URL.Path,
			"status":     rw.statusCode,
			"user_agent": r.UserAgent(),
			"remote_ip":  r.RemoteAddr,
			"duration":   time.Since(start).Milliseconds(),
		}).Info("HTTP request")
	})
}

// responseWriter is a wrapper around http.ResponseWriter to capture the status code
type responseWriter struct {
	http.ResponseWriter
	statusCode int
}

// WriteHeader captures the status code
func (rw *responseWriter) WriteHeader(code int) {
	rw.statusCode = code
	rw.ResponseWriter.WriteHeader(code)
}
