package handlers

import (
	"fmt"
	"net/http"
	"os"

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

	"veza-backend-api/internal/config"
	"veza-backend-api/internal/logging"
)

// FrontendLogHandler gère la réception des logs du frontend
type FrontendLogHandler struct {
	logger         *zap.Logger
	frontendLogger *logging.Logger
	logDir         string
	commonHandler  *CommonHandler
}

// NewFrontendLogHandler crée un nouveau handler pour les logs frontend
func NewFrontendLogHandler(cfg *config.Config, logger *zap.Logger) (*FrontendLogHandler, error) {
	logDir := cfg.LogDir
	if logDir == "" {
		logDir = "/var/log/veza"
	}

	// Créer le répertoire de logs s'il n'existe pas
	// En développement, utiliser un répertoire local si /var/log n'est pas accessible
	if err := os.MkdirAll(logDir, 0755); err != nil {
		// En développement, fallback vers un répertoire local
		if cfg.Env == "development" || cfg.Env == "dev" {
			fallbackDir := "./logs"
			if err2 := os.MkdirAll(fallbackDir, 0755); err2 != nil {
				return nil, fmt.Errorf("failed to create log directory %s (fallback %s also failed: %v): %w", logDir, fallbackDir, err2, err)
			}
			logDir = fallbackDir
		} else {
			return nil, fmt.Errorf("failed to create log directory %s: %w (hint: create it manually with 'sudo mkdir -p %s && sudo chown $USER:$USER %s')", logDir, err, logDir, logDir)
		}
	}

	// Créer un logger spécifique pour le frontend avec fichiers séparés
	frontendLogger, err := logging.NewLoggerWithFileRotation(logDir, "frontend", cfg.Env, cfg.LogLevel)
	if err != nil {
		return nil, fmt.Errorf("failed to create frontend logger: %w", err)
	}

	handler := &FrontendLogHandler{
		logger:         logger,
		frontendLogger: frontendLogger,
		logDir:         logDir,
		commonHandler:  NewCommonHandler(logger),
	}
	return handler, nil
}

// FrontendLogRequest représente une requête de log du frontend
type FrontendLogRequest struct {
	Timestamp string                 `json:"timestamp"`
	Level     string                 `json:"level"`
	Message   string                 `json:"message"`
	Context   map[string]interface{} `json:"context,omitempty"`
	Data      interface{}            `json:"data,omitempty"`
}

// ReceiveLog gère la réception d'un log du frontend
// @Summary      Receive frontend log
// @Description  Receive and store a log entry from the frontend application
// @Tags         Logging
// @Accept       json
// @Produce      json
// @Param        log  body      FrontendLogRequest  true  "Frontend log entry"
// @Success      200  {object}  handlers.APIResponse{data=object{received=bool}}
// @Failure      400  {object}  handlers.APIResponse "Invalid log entry"
// @Failure      500  {object}  handlers.APIResponse "Internal server error"
// @Router       /api/v1/logs/frontend [post]
func (h *FrontendLogHandler) ReceiveLog(c *gin.Context) {
	var logReq FrontendLogRequest
	if err := c.ShouldBindJSON(&logReq); err != nil {
		h.commonHandler.RespondWithError(c, http.StatusBadRequest, "Invalid log entry format", err)
		return
	}

	// Valider le niveau de log
	level := logReq.Level
	if level == "" {
		level = "INFO"
	}

	// Extraire le request_id du contexte si présent
	requestID := ""
	if logReq.Context != nil {
		if rid, ok := logReq.Context["request_id"].(string); ok {
			requestID = rid
		}
	}

	// Construire les champs zap
	fields := []zap.Field{
		zap.String("source", "frontend"),
		zap.String("level", level),
		zap.String("message", logReq.Message),
	}

	if requestID != "" {
		fields = append(fields, zap.String("request_id", requestID))
	}

	if logReq.Context != nil {
		// Ajouter les champs du contexte (en évitant les doublons)
		for k, v := range logReq.Context {
			if k != "request_id" { // Déjà ajouté
				fields = append(fields, zap.Any(k, v))
			}
		}
	}

	if logReq.Data != nil {
		fields = append(fields, zap.Any("data", logReq.Data))
	}

	// Logger selon le niveau
	switch level {
	case "DEBUG":
		h.frontendLogger.Debug(logReq.Message, fields...)
	case "INFO":
		h.frontendLogger.Info(logReq.Message, fields...)
	case "WARN":
		h.frontendLogger.Warn(logReq.Message, fields...)
	case "ERROR":
		h.frontendLogger.Error(logReq.Message, fields...)
	default:
		h.frontendLogger.Info(logReq.Message, fields...)
	}

	// Répondre avec succès
	// Action 1.3.2.1: Use wrapped format helper
	RespondSuccess(c, http.StatusOK, gin.H{
		"received": true,
		"level":    level,
	})
}
