package services

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"mime/multipart"
	"os"
	"path/filepath"
	"time"

	"github.com/google/uuid"

	"veza-backend-api/internal/models"
	"veza-backend-api/internal/types"
	"veza-backend-api/internal/utils"

	"gorm.io/gorm"
)

// UserRepository defines the interface for user repository operations
type UserRepository interface {
	GetByID(id string) (*models.User, error)
	GetByEmail(email string) (*models.User, error)
	GetByUsername(username string) (*models.User, error)
	Create(user *models.User) error
	Update(user *models.User) error
	Delete(id string) error
}

// UserService gère les opérations sur les utilisateurs
type UserService struct {
	userRepo     UserRepository
	db           *gorm.DB      // Optional DB access for settings
	cacheService *CacheService // BE-SVC-001: Cache service for user profiles
	uploadDir    string
}

// UpdateProfileRequest represents profile update data
type UpdateProfileRequest struct {
	FirstName      *string                `json:"first_name"`
	LastName       *string                `json:"last_name"`
	Username       *string                `json:"username"`
	Bio            *string                `json:"bio"`
	Location       *string                `json:"location"`
	BirthDate      *string                `json:"birth_date"`
	Gender         *string                `json:"gender"`
	Timezone       *string                `json:"timezone"`
	SocialLinks    map[string]interface{} `json:"social_links"`
	WebsiteURL     *string                `json:"website_url"`
	ProfilePrivacy *string                `json:"profile_privacy"`
}

// Profile represents a user profile with necessary fields
// MIGRATION UUID: ID et UserID migrés vers uuid.UUID
type Profile struct {
	ID          uuid.UUID              `json:"id"`
	UserID      uuid.UUID              `json:"user_id"`
	Username    string                 `json:"username"`
	FirstName   string                 `json:"first_name"`
	LastName    string                 `json:"last_name"`
	AvatarURL   *string                `json:"avatar_url"`
	Bio         *string                `json:"bio"`
	Location    *string                `json:"location"`
	Birthdate   *string                `json:"birthdate"`
	Gender      *string                `json:"gender"`
	SocialLinks map[string]interface{} `json:"social_links"`
	CreatedAt   time.Time              `json:"created_at"`
}

// UserStats est maintenant défini dans internal/types/stats.go
// Import: veza-backend-api/internal/types

// ProfileCompletion represents profile completion status
type ProfileCompletion struct {
	Percentage int      `json:"percentage"`
	Missing    []string `json:"missing"`
}

// NewUserService crée une nouvelle instance d'UserService
func NewUserService(userRepo UserRepository) *UserService {
	return &UserService{
		userRepo:  userRepo,
		uploadDir: "uploads/avatars",
	}
}

// SetCacheService définit le service de cache pour UserService
// BE-SVC-001: Implement caching layer for frequently accessed data
func (s *UserService) SetCacheService(cacheService *CacheService) {
	s.cacheService = cacheService
}

// NewUserServiceWithDB crée une nouvelle instance d'UserService avec accès DB
func NewUserServiceWithDB(userRepo UserRepository, db *gorm.DB) *UserService {
	return &UserService{
		userRepo:  userRepo,
		db:        db,
		uploadDir: "uploads/avatars",
	}
}

// SetUploadDir sets the upload directory (useful for testing)
func (s *UserService) SetUploadDir(dir string) {
	s.uploadDir = dir
}

// GetProfileByString récupère le profil d'un utilisateur par ID string (legacy method)
func (s *UserService) GetProfileByString(userID string) (*models.User, error) {
	user, err := s.userRepo.GetByID(userID)
	if err != nil {
		return nil, errors.New("user not found")
	}

	// PasswordHash est déjà exclu avec json:"-"
	return user, nil
}

// UpdateProfile met à jour le profil d'un utilisateur
// UpdateProfileLegacy updates user profile using a map (legacy method, kept for backward compatibility)
// DEPRECATED: Use UpdateProfile(userID uuid.UUID, req types.UpdateProfileRequest) instead
func (s *UserService) UpdateProfileLegacy(userID string, updates map[string]interface{}) (*models.User, error) {
	user, err := s.userRepo.GetByID(userID)
	if err != nil {
		return nil, errors.New("user not found")
	}

	// Appliquer les mises à jour
	if username, ok := updates["username"].(string); ok {
		user.Username = username
	}
	if email, ok := updates["email"].(string); ok {
		user.Email = email
	}

	// Sauvegarder les modifications
	err = s.userRepo.Update(user)
	if err != nil {
		return nil, err
	}

	// PasswordHash est déjà exclu avec json:"-"
	return user, nil
}

// GetByID retrieves a user by ID
func (s *UserService) GetByID(userID uuid.UUID) (*models.User, error) {
	return s.userRepo.GetByID(userID.String())
}

// GetProfileByID retrieves a user profile by ID (alias for GetByID for clarity)
func (s *UserService) GetProfileByID(userID uuid.UUID) (*models.User, error) {
	return s.GetByID(userID)
}

// GetByUsername retrieves a user by username
func (s *UserService) GetByUsername(username string) (*models.User, error) {
	return s.userRepo.GetByUsername(username)
}

// UpdateProfileWithRequest updates user profile with new request structure
func (s *UserService) UpdateProfileWithRequest(userID uuid.UUID, req *UpdateProfileRequest) (*models.User, error) {
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return nil, errors.New("user not found")
	}

	// Apply updates
	if req.Bio != nil {
		user.Bio = *req.Bio
	}
	// Add more field updates as needed

	// Save changes
	err = s.userRepo.Update(user)
	if err != nil {
		return nil, err
	}

	return user, nil
}

// GetProfile retrieves a user profile by ID
// requesterID can be nil for unauthenticated requests
// If profile is private and requesterID is different from userID, returns limited fields
// MIGRATION UUID: requesterID migré vers *uuid.UUID
// BE-SVC-001: Add caching for user profiles
func (s *UserService) GetProfile(userID uuid.UUID, requesterID *uuid.UUID) (*Profile, error) {
	ctx := context.Background()
	cacheConfig := DefaultCacheConfig()

	// Try to get from cache first
	if s.cacheService != nil {
		var cachedProfile Profile
		if err := s.cacheService.GetUser(ctx, userID, &cachedProfile); err == nil {
			// Cache hit - but we still need to check privacy settings
			// For now, return cached profile (privacy check would need to be cached too)
			return &cachedProfile, nil
		}
	}

	// Cache miss - fetch from database
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return nil, fmt.Errorf("user not found")
	}

	profile := s.userToProfile(user)

	// If profile is private and requester is different from owner, limit fields
	if !user.IsPublic && (requesterID == nil || *requesterID != userID) {
		profile.Bio = nil
		profile.Location = nil
		profile.Birthdate = nil
		profile.Gender = nil
	}

	// Cache the profile
	if s.cacheService != nil {
		if err := s.cacheService.SetUser(ctx, userID, profile, cacheConfig); err != nil {
			// Log error but don't fail the request
			// Could add logger here if available
		}
	}

	return profile, nil
}

// GetProfileByUsername retrieves a user profile by username
// requesterID can be nil for unauthenticated requests
// If profile is private and requesterID is different from userID, returns limited fields
// MIGRATION UUID: requesterID migré vers *uuid.UUID
// BE-SVC-001: Add caching for user profiles
func (s *UserService) GetProfileByUsername(username string, requesterID *uuid.UUID) (*Profile, error) {
	// Get user first to get userID for cache
	user, err := s.userRepo.GetByUsername(username)
	if err != nil {
		return nil, fmt.Errorf("user not found")
	}

	// Use GetProfile which handles caching
	return s.GetProfile(user.ID, requesterID)
}

// UpdateProfile updates a user profile and returns the updated profile
// BE-SVC-001: Invalidate cache on profile update
func (s *UserService) UpdateProfile(userID uuid.UUID, req types.UpdateProfileRequest) (*Profile, error) {
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return nil, fmt.Errorf("user not found")
	}

	// Invalidate cache before update
	if s.cacheService != nil {
		ctx := context.Background()
		if err := s.cacheService.InvalidateUserCache(ctx, userID); err != nil {
			// Log error but don't fail the request
		}
	}

	// Build updates map dynamically based on provided fields
	updates := make(map[string]interface{})

	if req.FirstName != nil && *req.FirstName != "" {
		updates["first_name"] = *req.FirstName
	}
	if req.LastName != nil && *req.LastName != "" {
		updates["last_name"] = *req.LastName
	}
	if req.Username != nil && *req.Username != "" {
		updates["username"] = *req.Username
		// Set username_changed_at when username changes
		now := time.Now()
		updates["username_changed_at"] = &now
		// T0219: Generate and update slug when username changes
		slug := utils.Slugify(*req.Username)
		// Simplified: let the database handle uniqueness via unique constraint
		updates["slug"] = slug
	}
	if req.Bio != nil && *req.Bio != "" {
		updates["bio"] = *req.Bio
	}
	if req.Location != nil && *req.Location != "" {
		updates["location"] = *req.Location
	}
	if req.BirthDate != nil && *req.BirthDate != "" {
		birthdate, err := time.Parse("2006-01-02", *req.BirthDate)
		if err == nil {
			updates["birthdate"] = &birthdate
		}
	}
	if req.Gender != nil && *req.Gender != "" {
		updates["gender"] = *req.Gender
	}
	if req.SocialLinks != nil {
		socialLinksJSON, _ := json.Marshal(req.SocialLinks)
		updates["social_links"] = string(socialLinksJSON)
	}

	// Apply updates to user object
	if firstname, ok := updates["first_name"].(string); ok {
		user.FirstName = firstname
	}
	if lastname, ok := updates["last_name"].(string); ok {
		user.LastName = lastname
	}
	if username, ok := updates["username"].(string); ok {
		user.Username = username
	}
	if slug, ok := updates["slug"].(string); ok {
		user.Slug = slug
	}
	if usernameChangedAt, ok := updates["username_changed_at"].(*time.Time); ok {
		user.UsernameChangedAt = usernameChangedAt
	}
	if bio, ok := updates["bio"].(string); ok {
		user.Bio = bio
	}
	if location, ok := updates["location"].(string); ok {
		user.Location = location
	}
	if birthdate, ok := updates["birthdate"].(*time.Time); ok {
		user.Birthdate = birthdate
	}
	if gender, ok := updates["gender"].(string); ok {
		user.Gender = gender
	}

	// Update social links
	if socialLinks, ok := updates["social_links"].(string); ok {
		user.SocialLinks = socialLinks
	}

	// Save changes
	err = s.userRepo.Update(user)
	if err != nil {
		return nil, fmt.Errorf("failed to update profile: %w", err)
	}

	// Return updated profile
	return s.userToProfile(user), nil
}

// userToProfile converts a models.User to a Profile struct
func (s *UserService) userToProfile(user *models.User) *Profile {
	var avatarURL *string
	if user.Avatar != "" {
		avatarURL = &user.Avatar
	}

	var bio *string
	if user.Bio != "" {
		bio = &user.Bio
	}

	var location *string
	if user.Location != "" {
		location = &user.Location
	}

	var birthdate *string
	if user.Birthdate != nil {
		birthdateStr := user.Birthdate.Format("2006-01-02")
		birthdate = &birthdateStr
	}

	var gender *string
	if user.Gender != "" {
		gender = &user.Gender
	}

	var socialLinks map[string]interface{}
	if user.SocialLinks != "" {
		_ = json.Unmarshal([]byte(user.SocialLinks), &socialLinks)
	}

	return &Profile{
		ID:          user.ID,
		UserID:      user.ID,
		Username:    user.Username,
		FirstName:   user.FirstName,
		LastName:    user.LastName,
		AvatarURL:   avatarURL,
		Bio:         bio,
		Location:    location,
		Birthdate:   birthdate,
		Gender:      gender,
		SocialLinks: socialLinks,
		CreatedAt:   user.CreatedAt,
	}
}

func (s *UserService) UploadAvatar(userID uuid.UUID, file *multipart.FileHeader) (string, error) {
	// Create uploads directory if it doesn't exist
	if err := os.MkdirAll(s.uploadDir, 0755); err != nil {
		return "", fmt.Errorf("failed to create upload directory: %w", err)
	}

	// Generate unique filename
	filename := fmt.Sprintf("%s_%s%s", userID.String(), uuid.New().String(), filepath.Ext(file.Filename))
	filePath := filepath.Join(s.uploadDir, filename)

	// Save file
	src, err := file.Open()
	if err != nil {
		return "", err
	}
	defer src.Close()

	dst, err := os.Create(filePath)
	if err != nil {
		return "", err
	}
	defer dst.Close()

	if _, err := dst.ReadFrom(src); err != nil {
		return "", err
	}

	// Return URL (relative path for frontend)
	// Note: We always return the relative path from "uploads/" for the URL
	// even if the physical storage is elsewhere during testing
	avatarURL := fmt.Sprintf("/uploads/avatars/%s", filename)
	return avatarURL, nil
}

// UpdateAvatarURL updates the avatar URL for a user
// T0221: Updates the avatar field in the users table
// T0222: Can accept empty string to set avatar to NULL
func (s *UserService) UpdateAvatarURL(userID uuid.UUID, avatarURL string) error {
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return fmt.Errorf("user not found")
	}

	// If avatarURL is empty string, set to empty (will be NULL in DB)
	user.Avatar = avatarURL
	if err := s.userRepo.Update(user); err != nil {
		return fmt.Errorf("failed to update avatar URL: %w", err)
	}

	return nil
}

// GetUserStats retrieves user statistics
func (s *UserService) GetUserStats(username string) (*types.UserStats, error) {
	// This would typically query the database for stats
	// For now, return empty stats
	return &types.UserStats{
		FollowersCount: 0,
		FollowingCount: 0,
		TracksCount:    0,
		PlaylistsCount: 0,
	}, nil
}

// ValidateUsername checks if a username is unique and if it can be changed (once per month)
func (s *UserService) ValidateUsername(userID uuid.UUID, username string) error {
	// Vérifier si username existe pour autre user
	existingUser, err := s.userRepo.GetByUsername(username)
	if err == nil && existingUser != nil && existingUser.ID != userID {
		return errors.New("username already taken")
	}

	// Vérifier si username modifiable (1 fois par mois)
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return fmt.Errorf("failed to check username change date: %w", err)
	}

	// Si le username actuel est le même, pas besoin de vérifier la date de changement
	if user.Username == username {
		return nil
	}

	// Vérifier si username_changed_at existe et si moins de 30 jours
	if user.UsernameChangedAt != nil {
		timeSinceChange := time.Since(*user.UsernameChangedAt)
		if timeSinceChange < 30*24*time.Hour {
			return errors.New("username can only be changed once per month")
		}
	}

	return nil
}

// CanChangeUsername checks if a user can change their username (once per month)
func (s *UserService) CanChangeUsername(userID uuid.UUID) (bool, error) {
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return false, err
	}

	// If UsernameChangedAt is nil, user can change username
	if user.UsernameChangedAt == nil {
		return true, nil
	}

	// Check if it's been at least 1 month since last change
	oneMonthAgo := time.Now().AddDate(0, -1, 0)
	return user.UsernameChangedAt.Before(oneMonthAgo), nil
}

// CalculateProfileCompletion calculates the profile completion percentage
// T0220: Returns percentage (0-100) and list of missing required fields
func (s *UserService) CalculateProfileCompletion(userID uuid.UUID) (*ProfileCompletion, error) {
	// Get profile as owner (to see all fields)
	profile, err := s.GetProfile(userID, &userID)
	if err != nil {
		return nil, fmt.Errorf("user not found")
	}

	totalFields := 5
	completedFields := 0
	missing := []string{}

	// Check username
	if profile.Username != "" {
		completedFields++
	} else {
		missing = append(missing, "username")
	}

	// Check first_name
	if profile.FirstName != "" {
		completedFields++
	} else {
		missing = append(missing, "first_name")
	}

	// Check last_name
	if profile.LastName != "" {
		completedFields++
	} else {
		missing = append(missing, "last_name")
	}

	// Check bio
	if profile.Bio != nil && *profile.Bio != "" {
		completedFields++
	} else {
		missing = append(missing, "bio")
	}

	// Check avatar
	if profile.AvatarURL != nil && *profile.AvatarURL != "" {
		completedFields++
	} else {
		missing = append(missing, "avatar")
	}

	// Check social links (at least one)
	if len(profile.SocialLinks) > 0 {
		completedFields++
	} else {
		missing = append(missing, "social_links")
	}

	// Adjust totalFields
	totalFields = 6

	// Calculate percentage
	percentage := (completedFields * 100) / totalFields

	return &ProfileCompletion{
		Percentage: percentage,
		Missing:    missing,
	}, nil
}

// UpdateProfileByID updates a user profile by ID with the new request structure
func (s *UserService) UpdateProfileByID(userID uuid.UUID, req *UpdateProfileRequest) (*models.User, error) {
	user, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return nil, errors.New("user not found")
	}

	// Apply updates
	if req.FirstName != nil && *req.FirstName != "" {
		user.FirstName = *req.FirstName
	}
	if req.LastName != nil && *req.LastName != "" {
		user.LastName = *req.LastName
	}
	if req.Username != nil && *req.Username != "" {
		user.Username = *req.Username
		now := time.Now()
		user.UsernameChangedAt = &now
	}
	if req.Bio != nil {
		user.Bio = *req.Bio
	}
	if req.Location != nil {
		user.Location = *req.Location
	}
	if req.BirthDate != nil && *req.BirthDate != "" {
		birthdate, err := time.Parse("2006-01-02", *req.BirthDate)
		if err == nil {
			user.Birthdate = &birthdate
		}
	}
	if req.Gender != nil {
		user.Gender = *req.Gender
	}

	// Save changes
	err = s.userRepo.Update(user)
	if err != nil {
		return nil, err
	}

	return user, nil
}

// GetUserSettings récupère les paramètres utilisateur
// T0231: Récupère user_settings depuis DB et user_profiles pour language, timezone, theme
func (s *UserService) GetUserSettings(userID uuid.UUID) (*types.UserSettingsResponse, error) {
	if s.db == nil {
		return nil, fmt.Errorf("database access not available")
	}

	// Récupérer ou créer user_settings
	var settings models.UserSettings
	result := s.db.Where("user_id = ?", userID).First(&settings)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			// Créer settings par défaut
			settings = models.UserSettings{
				UserID:               userID,
				EmailNotifications:   true,
				PushNotifications:    true,
				BrowserNotifications: true,
				EmailOnFollow:        true,
				EmailOnLike:          true,
				EmailOnComment:       true,
				EmailOnMessage:       true,
				EmailOnMention:       true,
				AllowSearchIndexing:  true,
				ShowActivity:         true,
				Autoplay:             true,
			}
			if err := s.db.Create(&settings).Error; err != nil {
				return nil, fmt.Errorf("failed to create default settings: %w", err)
			}
		} else {
			return nil, fmt.Errorf("failed to get settings: %w", result.Error)
		}
	}

	// Récupérer user_profiles pour preferences (language, timezone, theme)
	// T0233: Récupérer depuis user_profiles avec création auto si n'existe pas
	var profile models.UserProfile
	result = s.db.Where("user_id = ?", userID).First(&profile)
	if result.Error != nil {
		if result.Error == gorm.ErrRecordNotFound {
			// Créer profile par défaut
			profile = models.UserProfile{
				UserID:   userID,
				Language: "en",
				Timezone: "UTC",
				Theme:    "auto",
			}
			if err := s.db.Create(&profile).Error; err != nil {
				return nil, fmt.Errorf("failed to create default profile: %w", err)
			}
		} else {
			return nil, fmt.Errorf("failed to get profile: %w", result.Error)
		}
	}

	language := profile.Language
	timezone := profile.Timezone
	// theme := profile.Theme // Not used in PreferenceSettings (no Theme field)

	return &types.UserSettingsResponse{
		Notifications: types.NotificationSettings{
			Email:     settings.EmailNotifications,
			Push:      settings.PushNotifications,
			InApp:     settings.BrowserNotifications,
			Comments:  settings.EmailOnComment,
			Likes:     settings.EmailOnLike,
			Followers: settings.EmailOnFollow,
			Mentions:  settings.EmailOnMention,
			Playlist:  false, // Not mapped from settings
		},
		Privacy: types.PrivacySettings{
			ProfileVisibility: "public", // Default, should be read from settings if available
			PlaylistsPublic:   true,     // Default, should be read from settings if available
		},
		Content: types.ContentSettings{
			ExplicitContent: settings.ExplicitContent,
		},
		Preferences: types.PreferenceSettings{
			Language:   language,
			Timezone:   timezone,
			DateFormat: "YYYY-MM-DD", // Default
		},
	}, nil
}

// UpdateUserSettings met à jour les paramètres utilisateur
// T0232: Mettre à jour user_settings et user_profiles en DB
func (s *UserService) UpdateUserSettings(userID uuid.UUID, req *types.UpdateSettingsRequest) error {
	if s.db == nil {
		return fmt.Errorf("database access not available")
	}

	// Mettre à jour user_settings
	if req.Notifications != nil || req.Privacy != nil || req.Content != nil {
		updates := map[string]interface{}{}

		if req.Notifications != nil {
			updates["email_notifications"] = req.Notifications.Email
			updates["push_notifications"] = req.Notifications.Push
			updates["browser_notifications"] = req.Notifications.InApp
			updates["email_on_follow"] = req.Notifications.Followers
			updates["email_on_like"] = req.Notifications.Likes
			updates["email_on_comment"] = req.Notifications.Comments
			updates["email_on_mention"] = req.Notifications.Mentions
			// EmailOnMessage and EmailMarketing not mapped (no corresponding fields in NotificationSettings)
		}

		if req.Privacy != nil {
			// AllowSearchIndexing and ShowActivity not mapped (no corresponding fields in PrivacySettings)
			// PrivacySettings only has ProfileVisibility and PlaylistsPublic
		}

		if req.Content != nil {
			updates["explicit_content"] = req.Content.ExplicitContent
			// Autoplay not available in ContentSettings type
		}

		if len(updates) > 0 {
			// S'assurer que user_settings existe d'abord
			var settings models.UserSettings
			result := s.db.Where("user_id = ?", userID).First(&settings)
			if result.Error == gorm.ErrRecordNotFound {
				// Créer settings par défaut si n'existe pas
				settings = models.UserSettings{
					UserID:               userID,
					EmailNotifications:   true,
					PushNotifications:    true,
					BrowserNotifications: true,
					EmailOnFollow:        true,
					EmailOnLike:          true,
					EmailOnComment:       true,
					EmailOnMessage:       true,
					EmailOnMention:       true,
					AllowSearchIndexing:  true,
					ShowActivity:         true,
					Autoplay:             true,
				}
				if err := s.db.Create(&settings).Error; err != nil {
					return fmt.Errorf("failed to create default settings: %w", err)
				}
			} else if result.Error != nil {
				return fmt.Errorf("failed to get settings: %w", result.Error)
			}

			// Mettre à jour
			if err := s.db.Model(&models.UserSettings{}).Where("user_id = ?", userID).Updates(updates).Error; err != nil {
				return fmt.Errorf("failed to update settings: %w", err)
			}
		}
	}

	// Mettre à jour user_profiles (preferences)
	// T0233: Mettre à jour user_profiles avec création auto si n'existe pas
	if req.Preferences != nil {
		profileUpdates := map[string]interface{}{}
		if req.Preferences.Language != "" {
			profileUpdates["language"] = req.Preferences.Language
		}
		if req.Preferences.Timezone != "" {
			profileUpdates["timezone"] = req.Preferences.Timezone
		}
		// Theme not available in PreferenceSettings type (only Language, Timezone, DateFormat)

		if len(profileUpdates) > 0 {
			// S'assurer que user_profiles existe d'abord
			var profile models.UserProfile
			result := s.db.Where("user_id = ?", userID).First(&profile)
			if result.Error == gorm.ErrRecordNotFound {
				// Créer profile par défaut si n'existe pas
				profile = models.UserProfile{
					UserID:   userID,
					Language: "en",
					Timezone: "UTC",
					Theme:    "auto",
				}
				// Appliquer les updates avant création
				if lang, ok := profileUpdates["language"].(string); ok {
					profile.Language = lang
				}
				if tz, ok := profileUpdates["timezone"].(string); ok {
					profile.Timezone = tz
				}
				if th, ok := profileUpdates["theme"].(string); ok {
					profile.Theme = th
				}
				if err := s.db.Create(&profile).Error; err != nil {
					return fmt.Errorf("failed to create default profile: %w", err)
				}
			} else if result.Error != nil {
				return fmt.Errorf("failed to get profile: %w", result.Error)
			} else {
				// Mettre à jour
				if err := s.db.Model(&models.UserProfile{}).Where("user_id = ?", userID).Updates(profileUpdates).Error; err != nil {
					return fmt.Errorf("failed to update profile: %w", err)
				}
			}
		}
	}

	return nil
}

// DeleteUser soft deletes a user
// BE-API-041: Implement user delete endpoint with soft delete support
func (s *UserService) DeleteUser(ctx context.Context, userID uuid.UUID) error {
	// Check if user exists
	_, err := s.userRepo.GetByID(userID.String())
	if err != nil {
		return fmt.Errorf("user not found")
	}

	// Use repository Delete method (soft delete via GORM)
	if err := s.userRepo.Delete(userID.String()); err != nil {
		return fmt.Errorf("failed to delete user: %w", err)
	}

	// Also set is_active to false for consistency
	if s.db != nil {
		if err := s.db.WithContext(ctx).Model(&models.User{}).
			Where("id = ?", userID).
			Update("is_active", false).Error; err != nil {
			// Log but don't fail if this update fails
			return fmt.Errorf("failed to deactivate user: %w", err)
		}
	}

	return nil
}
