//go:build ignore
// +build ignore

// TODO: Réactiver two_factor_handlers après stabilisation du noyau et alignement des services (AuthService.GetUserByID)

package handlers

import (
	"net/http"

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

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

// TwoFactorHandlers handles 2FA-related API endpoints
type TwoFactorHandlers struct {
	twoFactorService *services.TwoFactorService
	authService      *services.AuthService
	logger           *zap.Logger
}

// NewTwoFactorHandlers creates new 2FA handlers
func NewTwoFactorHandlers(twoFactorService *services.TwoFactorService, authService *services.AuthService, logger *zap.Logger) *TwoFactorHandlers {
	return &TwoFactorHandlers{
		twoFactorService: twoFactorService,
		authService:      authService,
		logger:           logger,
	}
}

// InitTwoFactorHandlers initializes 2FA handlers
func InitTwoFactorHandlers(twoFactorService *services.TwoFactorService, authService *services.AuthService, logger *zap.Logger) {
	handlers := NewTwoFactorHandlers(twoFactorService, authService, logger)

	// Store handlers globally for route registration
	TwoFactorHandlersInstance = handlers
}

// TwoFactorHandlersInstance holds the global 2FA handlers instance
var TwoFactorHandlersInstance *TwoFactorHandlers

// SetupTwoFactor initiates 2FA setup for a user
func (h *TwoFactorHandlers) SetupTwoFactor(c *gin.Context) {
	userID := c.GetInt64("user_id")

	// Get user information
	user, err := h.authService.GetUserByID(c.Request.Context(), userID)
	if err != nil {
		h.logger.Error("Failed to get user", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get user information"})
		return
	}

	// Check if 2FA is already enabled
	enabled, err := h.twoFactorService.GetTwoFactorStatus(c.Request.Context(), userID)
	if err != nil {
		h.logger.Error("Failed to get 2FA status", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get 2FA status"})
		return
	}

	if enabled {
		c.JSON(http.StatusBadRequest, gin.H{"error": "2FA is already enabled"})
		return
	}

	// Generate 2FA setup
	setup, err := h.twoFactorService.GenerateSecret(user)
	if err != nil {
		h.logger.Error("Failed to generate 2FA setup", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate 2FA setup"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"setup":   setup,
	})
}

// EnableTwoFactor enables 2FA for a user
func (h *TwoFactorHandlers) EnableTwoFactor(c *gin.Context) {
	userID := c.GetInt64("user_id")

	var req struct {
		Secret        string   `json:"secret" binding:"required"`
		Code          string   `json:"code" binding:"required"`
		RecoveryCodes []string `json:"recovery_codes" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Verify the code first
	valid, err := h.twoFactorService.VerifyTwoFactor(c.Request.Context(), userID, req.Code)
	if err != nil {
		h.logger.Error("Failed to verify 2FA code", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to verify 2FA code"})
		return
	}

	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 2FA code"})
		return
	}

	// Enable 2FA
	err = h.twoFactorService.EnableTwoFactor(c.Request.Context(), userID, req.Secret, req.RecoveryCodes)
	if err != nil {
		h.logger.Error("Failed to enable 2FA", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to enable 2FA"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "2FA enabled successfully",
	})
}

// DisableTwoFactor disables 2FA for a user
func (h *TwoFactorHandlers) DisableTwoFactor(c *gin.Context) {
	userID := c.GetInt64("user_id")

	var req struct {
		Code string `json:"code" binding:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Verify the code first
	valid, err := h.twoFactorService.VerifyTwoFactor(c.Request.Context(), userID, req.Code)
	if err != nil {
		h.logger.Error("Failed to verify 2FA code", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to verify 2FA code"})
		return
	}

	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 2FA code"})
		return
	}

	// Disable 2FA
	err = h.twoFactorService.DisableTwoFactor(c.Request.Context(), userID)
	if err != nil {
		h.logger.Error("Failed to disable 2FA", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to disable 2FA"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "2FA disabled successfully",
	})
}

// VerifyTwoFactor verifies a 2FA code
func (h *TwoFactorHandlers) VerifyTwoFactor(c *gin.Context) {
	userID := c.GetInt64("user_id")

	var req services.TwoFactorVerification
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Verify the code
	valid, err := h.twoFactorService.VerifyTwoFactor(c.Request.Context(), userID, req.Code)
	if err != nil {
		h.logger.Error("Failed to verify 2FA code", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to verify 2FA code"})
		return
	}

	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid 2FA code"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "2FA code verified successfully",
	})
}

// GetTwoFactorStatus gets the 2FA status for a user
func (h *TwoFactorHandlers) GetTwoFactorStatus(c *gin.Context) {
	userID := c.GetInt64("user_id")

	enabled, err := h.twoFactorService.GetTwoFactorStatus(c.Request.Context(), userID)
	if err != nil {
		h.logger.Error("Failed to get 2FA status", zap.Error(err))
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get 2FA status"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"enabled": enabled,
	})
}
