package logging

import (
	"io"
	"os"
	"path/filepath"
	"time"

	"counter/internal/infrastructure/config"

	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
)

// Logger interface defines the contract for logging
type Logger interface {
	Info(args ...interface{})
	Infof(format string, args ...interface{})
	Warn(args ...interface{})
	Warnf(format string, args ...interface{})
	Error(args ...interface{})
	Errorf(format string, args ...interface{})
	Fatal(args ...interface{})
	Fatalf(format string, args ...interface{})
	WithFields(fields logrus.Fields) *logrus.Entry
	WithError(err error) *logrus.Entry
}

// LogrusLogger implements the Logger interface using logrus
type LogrusLogger struct {
	*logrus.Logger
}

// InitLogger initializes the structured logger with file output
func InitLogger(cfg *config.Config) (Logger, error) {
	logger := logrus.New()

	// Set log level based on configuration
	level, err := logrus.ParseLevel(cfg.LogLevel)
	if err != nil {
		level = logrus.InfoLevel
	}
	logger.SetLevel(level)

	// Set JSON formatter for structured logging
	logger.SetFormatter(&logrus.JSONFormatter{
		TimestampFormat: time.RFC3339,
		FieldMap: logrus.FieldMap{
			logrus.FieldKeyTime:  "timestamp",
			logrus.FieldKeyLevel: "level",
			logrus.FieldKeyMsg:   "message",
		},
	})

	// Create log directory if it doesn't exist
	if err := os.MkdirAll(cfg.LogDir, 0755); err != nil {
		return nil, err
	}

	// Create log file with timestamp
	logFile := filepath.Join(cfg.LogDir, "app.log")
	file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		return nil, err
	}

	// Set output to both file and stdout
	multiWriter := io.MultiWriter(os.Stdout, file)
	logger.SetOutput(multiWriter)

	// Log initialization with default fields
	logger.WithFields(logrus.Fields{
		"service":     "counter-app",
		"environment": string(cfg.Environment),
		"version":     "1.0.0",
	}).Info("Logger initialized successfully")

	return &LogrusLogger{Logger: logger}, nil
}

// LoggingMiddleware creates a Gin middleware for HTTP request logging
func LoggingMiddleware(logger Logger, cfg *config.Config) gin.HandlerFunc {
	return gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
		// Create structured log entry with default fields
		entry := logger.WithFields(logrus.Fields{
			"service":     "counter-app",
			"environment": string(cfg.Environment),
			"version":     "1.0.0",
			"method":      param.Method,
			"path":        param.Path,
			"status":      param.StatusCode,
			"latency":     param.Latency.String(),
			"client_ip":   param.ClientIP,
			"user_agent":  param.Request.UserAgent(),
			"timestamp":   param.TimeStamp.Format(time.RFC3339),
		})

		// Set log level based on status code
		switch {
		case param.StatusCode >= 500:
			entry.Error("HTTP Request")
		case param.StatusCode >= 400:
			entry.Warn("HTTP Request")
		default:
			entry.Info("HTTP Request")
		}

		// Return empty string since we're handling logging ourselves
		return ""
	})
}
