package handlers

import (
	"context"
	"net/http"

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

	"veza-backend-api/internal/middleware"
)

// CSRFHandler gère les handlers pour la protection CSRF
type CSRFHandler struct {
	csrfMiddleware CSRFMiddlewareInterface
	logger         *zap.Logger
}

// CSRFMiddlewareInterface defines methods needed for CSRF handler
type CSRFMiddlewareInterface interface {
	GetToken(ctx context.Context, userID uuid.UUID) (string, error)
}

// NewCSRFHandler crée un nouveau handler CSRF
func NewCSRFHandler(csrfMiddleware *middleware.CSRFMiddleware, logger *zap.Logger) *CSRFHandler {
	return &CSRFHandler{
		csrfMiddleware: csrfMiddleware,
		logger:         logger,
	}
}

// NewCSRFHandlerWithInterface creates a new CSRF handler with interface (for testing)
func NewCSRFHandlerWithInterface(csrfMiddleware CSRFMiddlewareInterface, logger *zap.Logger) *CSRFHandler {
	return &CSRFHandler{
		csrfMiddleware: csrfMiddleware,
		logger:         logger,
	}
}

// GetCSRFToken retourne un token CSRF pour l'utilisateur authentifié
// GET /api/v1/csrf-token
func (h *CSRFHandler) GetCSRFToken() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Récupérer le userID depuis le contexte (défini par AuthMiddleware.OptionalAuth)
		userIDInterface, exists := c.Get("user_id")
		if !exists {
			// Si pas d'utilisateur authentifié, on retourne un token public/anonyme
			// Le middleware CSRF côté serveur ignore la validation si user_id est absent du contexte
			// Action 1.3.2.1: Use wrapped format helper
			RespondSuccess(c, http.StatusOK, gin.H{
				"csrf_token": "public-anonymous-token",
			})
			return
		}

		userID, ok := userIDInterface.(uuid.UUID)
		if !ok {
			h.logger.Error("Invalid user_id type in context")
			// Action 1.3.2.1: Use wrapped format helper for errors
			RespondWithError(c, 500, "Internal server error")
			return
		}

		// Générer ou récupérer le token CSRF
		ctx := c.Request.Context()
		token, err := h.csrfMiddleware.GetToken(ctx, userID)
		if err != nil {
			h.logger.Error("Failed to get CSRF token",
				zap.Error(err),
				zap.String("user_id", userID.String()),
			)
			// Action 1.3.2.1: Use wrapped format helper for errors
			RespondWithError(c, 500, "Failed to generate CSRF token")
			return
		}

		// Retourner le token
		// Action 1.3.2.1: Use wrapped format helper
		RespondSuccess(c, http.StatusOK, gin.H{
			"csrf_token": token,
		})
	}
}
