package handlers

import (
	"fmt"
	"net/http"
	"time"

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

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

// UserServiceInterfaceForSettings defines the interface for user service operations needed by settings handler
// This allows for easier testing with mocks
type UserServiceInterfaceForSettings interface {
	GetUserSettings(userID uuid.UUID) (*types.UserSettingsResponse, error)
	UpdateUserSettings(userID uuid.UUID, req *types.UpdateSettingsRequest) error
}

// SettingsHandler handles settings-related operations
type SettingsHandler struct {
	userService   UserServiceInterfaceForSettings
	commonHandler *CommonHandler
}

// NewSettingsHandler creates a new SettingsHandler instance
func NewSettingsHandler(userService *services.UserService, logger *zap.Logger) *SettingsHandler {
	return &SettingsHandler{
		userService:   userService,
		commonHandler: NewCommonHandler(logger),
	}
}

// NewSettingsHandlerWithInterface creates a new SettingsHandler with an interface (for testing)
func NewSettingsHandlerWithInterface(userService UserServiceInterfaceForSettings, logger *zap.Logger) *SettingsHandler {
	return &SettingsHandler{
		userService:   userService,
		commonHandler: NewCommonHandler(logger),
	}
}

// UserSettingsResponse represents the response structure for user settings
type UserSettingsResponse struct {
	Notifications NotificationSettings `json:"notifications"`
	Privacy       PrivacySettings      `json:"privacy"`
	Content       ContentSettings      `json:"content"`
	Preferences   PreferenceSettings   `json:"preferences"`
}

// NotificationSettings represents notification preferences
type NotificationSettings struct {
	EmailNotifications   bool `json:"email_notifications"`
	PushNotifications    bool `json:"push_notifications"`
	BrowserNotifications bool `json:"browser_notifications"`
	EmailOnFollow        bool `json:"email_on_follow"`
	EmailOnLike          bool `json:"email_on_like"`
	EmailOnComment       bool `json:"email_on_comment"`
	EmailOnMessage       bool `json:"email_on_message"`
	EmailOnMention       bool `json:"email_on_mention"`
	EmailMarketing       bool `json:"email_marketing"`
}

// PrivacySettings represents privacy preferences
type PrivacySettings struct {
	AllowSearchIndexing bool `json:"allow_search_indexing"`
	ShowActivity        bool `json:"show_activity"`
}

// ContentSettings represents content preferences
type ContentSettings struct {
	ExplicitContent bool `json:"explicit_content"`
	Autoplay        bool `json:"autoplay"`
}

// PreferenceSettings represents user preferences
type PreferenceSettings struct {
	Language string `json:"language"` // ISO 639-1
	Timezone string `json:"timezone"`
	Theme    string `json:"theme"` // light, dark, auto
}

// GetSettings retrieves user settings
// T0231: Utilise l'utilisateur authentifié depuis le contexte (route /users/settings sans :id)
func (h *SettingsHandler) GetSettings(c *gin.Context) {
	// Récupérer l'ID utilisateur depuis le contexte d'authentification
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return // Erreur déjà envoyée par GetUserIDUUID
	}
	if userID == uuid.Nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	settings, err := h.userService.GetUserSettings(userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get settings"})
		return
	}

	RespondSuccess(c, http.StatusOK, settings)
}

// UpdateSettings updates user settings
// T0232: Utilise l'utilisateur authentifié depuis le contexte (route /users/settings sans :id)
func (h *SettingsHandler) UpdateSettings(c *gin.Context) {
	// Récupérer l'ID utilisateur depuis le contexte d'authentification
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return // Erreur déjà envoyée par GetUserIDUUID
	}
	if userID == uuid.Nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	var req types.UpdateSettingsRequest
	if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
		RespondWithAppError(c, appErr)
		return
	}

	// Valider preferences si fournies
	if req.Preferences != nil {
		if err := h.validatePreferences(req.Preferences); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
			return
		}
	}

	// Mettre à jour settings
	if err := h.userService.UpdateUserSettings(userID, &req); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to update settings"})
		return
	}

	RespondSuccess(c, http.StatusOK, gin.H{"message": "settings updated"})
}

// validatePreferences validates preference settings
func (h *SettingsHandler) validatePreferences(prefs *types.PreferenceSettings) error {
	// Valider language (ISO 639-1)
	validLanguages := []string{"en", "fr", "es", "de", "it", "pt", "ru", "ja", "zh", "ko"}
	if prefs.Language != "" {
		valid := false
		for _, lang := range validLanguages {
			if prefs.Language == lang {
				valid = true
				break
			}
		}
		if !valid {
			return fmt.Errorf("invalid language code: %s", prefs.Language)
		}
	}

	// Valider timezone (IANA timezone)
	if prefs.Timezone != "" {
		if _, err := time.LoadLocation(prefs.Timezone); err != nil {
			return fmt.Errorf("invalid timezone: %s", prefs.Timezone)
		}
	}

	return nil
}
