using Microsoft.EntityFrameworkCore; using Nuuru.Server.Data; using Nuuru.Server.DTOs.UserSettings; using Nuuru.Server.Models; using Nuuru.Server.Services.Search; namespace Nuuru.Server.Services { public interface IUserSettingsService { Task GetSettingsAsync(Guid userId); Task UpdateSettingsAsync(Guid userId, UpdateUserSettingsRequest dto); Task IsNotificationEnabledAsync(Guid userId, NotificationType type); Task> AreNotificationsEnabledAsync(IEnumerable userIds, NotificationType type); Task GetAutoWatchPreferencesAsync(Guid userId); Task GetDefaultSearchQueryAsync(Guid userId); } public class UserSettingsService : IUserSettingsService { private readonly ApplicationDbContext _context; public UserSettingsService(ApplicationDbContext context) { _context = context; } public async Task GetSettingsAsync(Guid userId) { var settings = await GetOrCreateAsync(userId); return ToDto(settings); } public async Task UpdateSettingsAsync(Guid userId, UpdateUserSettingsRequest dto) { var settings = await GetOrCreateAsync(userId); // Appearance if (dto.Theme != null) settings.Theme = dto.Theme; // Notification toggles if (dto.NotifyOnPostComment.HasValue) settings.NotifyOnPostComment = dto.NotifyOnPostComment.Value; if (dto.NotifyOnMention.HasValue) settings.NotifyOnMention = dto.NotifyOnMention.Value; if (dto.NotifyOnForumQuote.HasValue) settings.NotifyOnForumQuote = dto.NotifyOnForumQuote.Value; if (dto.NotifyOnWatchedPostComment.HasValue) settings.NotifyOnWatchedPostComment = dto.NotifyOnWatchedPostComment.Value; if (dto.NotifyOnWatchedThreadReply.HasValue) settings.NotifyOnWatchedThreadReply = dto.NotifyOnWatchedThreadReply.Value; if (dto.NotifyOnPrivateMessage.HasValue) settings.NotifyOnPrivateMessage = dto.NotifyOnPrivateMessage.Value; if (dto.NotifyOnGroupMessage.HasValue) settings.NotifyOnGroupMessage = dto.NotifyOnGroupMessage.Value; if (dto.NotifyOnReaction.HasValue) settings.NotifyOnReaction = dto.NotifyOnReaction.Value; if (dto.NotifyOnFriendAdded.HasValue) settings.NotifyOnFriendAdded = dto.NotifyOnFriendAdded.Value; if (dto.NotifyOnEnemyAdded.HasValue) settings.NotifyOnEnemyAdded = dto.NotifyOnEnemyAdded.Value; if (dto.NotifyOnFriendRemoved.HasValue) settings.NotifyOnFriendRemoved = dto.NotifyOnFriendRemoved.Value; // Auto-watch toggles if (dto.AutoWatchOwnPosts.HasValue) settings.AutoWatchOwnPosts = dto.AutoWatchOwnPosts.Value; if (dto.AutoWatchOnPostComment.HasValue) settings.AutoWatchOnPostComment = dto.AutoWatchOnPostComment.Value; if (dto.AutoWatchOnForumThreadCreate.HasValue) settings.AutoWatchOnForumThreadCreate = dto.AutoWatchOnForumThreadCreate.Value; if (dto.AutoWatchOnForumThreadReply.HasValue) settings.AutoWatchOnForumThreadReply = dto.AutoWatchOnForumThreadReply.Value; // Auto-update if (dto.AutoUpdateEnabled.HasValue) settings.AutoUpdateEnabled = dto.AutoUpdateEnabled.Value; if (dto.AutoNavigateNextPage.HasValue) settings.AutoNavigateNextPage = dto.AutoNavigateNextPage.Value; // Search if (dto.DefaultSearchQuery != null) settings.DefaultSearchQuery = dto.DefaultSearchQuery; // Comments if (dto.FloatingCommentEditor.HasValue) settings.FloatingCommentEditor = dto.FloatingCommentEditor.Value; // Social / Privacy if (dto.BlockMentionsFromEnemies.HasValue) settings.BlockMentionsFromEnemies = dto.BlockMentionsFromEnemies.Value; if (dto.OnlyAllowDmsFromFriends.HasValue) settings.OnlyAllowDmsFromFriends = dto.OnlyAllowDmsFromFriends.Value; await _context.SaveChangesAsync(); return ToDto(settings); } public async Task IsNotificationEnabledAsync(Guid userId, NotificationType type) { var settings = await GetOrCreateAsync(userId); return IsEnabled(settings, type); } public async Task> AreNotificationsEnabledAsync(IEnumerable userIds, NotificationType type) { var ids = userIds.Distinct().ToList(); if (ids.Count == 0) return new Dictionary(); var allSettings = await _context.UserSettings .Where(s => ids.Contains(s.UserId)) .ToListAsync(); var settingsMap = allSettings.ToDictionary(s => s.UserId); var result = new Dictionary(); foreach (var id in ids) { if (settingsMap.TryGetValue(id, out var settings)) { result[id] = IsEnabled(settings, type); } else { // No settings row = all defaults = all enabled result[id] = true; } } return result; } public async Task GetAutoWatchPreferencesAsync(Guid userId) { return await GetOrCreateAsync(userId); } public async Task GetDefaultSearchQueryAsync(Guid userId) { var userQueryState = await _context.Users .Where(u => u.Id == userId) .Select(u => new { u.IsBabyMode, DefaultSearchQuery = _context.UserSettings .Where(s => s.UserId == u.Id) .Select(s => s.DefaultSearchQuery) .FirstOrDefault() }) .FirstOrDefaultAsync(); if (userQueryState == null) return null; var query = string.IsNullOrWhiteSpace(userQueryState.DefaultSearchQuery) ? null : userQueryState.DefaultSearchQuery; if (!userQueryState.IsBabyMode) return query; return string.IsNullOrWhiteSpace(query) ? SearchDefaults.DefaultQuery : $"{query} {SearchDefaults.DefaultQuery}"; } private async Task GetOrCreateAsync(Guid userId) { var settings = await _context.UserSettings.FindAsync(userId); if (settings != null) return settings; settings = new Models.UserSettings { UserId = userId }; _context.UserSettings.Add(settings); await _context.SaveChangesAsync(); return settings; } private static bool IsEnabled(Models.UserSettings settings, NotificationType type) => type switch { NotificationType.CommentOnPost => settings.NotifyOnPostComment, NotificationType.Mention => settings.NotifyOnMention, NotificationType.ForumQuote => settings.NotifyOnForumQuote, NotificationType.WatchedPostComment => settings.NotifyOnWatchedPostComment, NotificationType.WatchedThreadReply => settings.NotifyOnWatchedThreadReply, NotificationType.PrivateMessage => settings.NotifyOnPrivateMessage, NotificationType.GroupMessage => settings.NotifyOnGroupMessage, NotificationType.Reaction => settings.NotifyOnReaction, NotificationType.FriendAdded => settings.NotifyOnFriendAdded, NotificationType.EnemyAdded => settings.NotifyOnEnemyAdded, NotificationType.FriendRemoved => settings.NotifyOnFriendRemoved, _ => true, }; private static UserSettingsDto ToDto(Models.UserSettings settings) => new() { Theme = settings.Theme, NotifyOnPostComment = settings.NotifyOnPostComment, NotifyOnMention = settings.NotifyOnMention, NotifyOnForumQuote = settings.NotifyOnForumQuote, NotifyOnWatchedPostComment = settings.NotifyOnWatchedPostComment, NotifyOnWatchedThreadReply = settings.NotifyOnWatchedThreadReply, NotifyOnPrivateMessage = settings.NotifyOnPrivateMessage, NotifyOnGroupMessage = settings.NotifyOnGroupMessage, NotifyOnReaction = settings.NotifyOnReaction, NotifyOnFriendAdded = settings.NotifyOnFriendAdded, NotifyOnEnemyAdded = settings.NotifyOnEnemyAdded, NotifyOnFriendRemoved = settings.NotifyOnFriendRemoved, AutoWatchOwnPosts = settings.AutoWatchOwnPosts, AutoWatchOnPostComment = settings.AutoWatchOnPostComment, AutoWatchOnForumThreadCreate = settings.AutoWatchOnForumThreadCreate, AutoWatchOnForumThreadReply = settings.AutoWatchOnForumThreadReply, AutoUpdateEnabled = settings.AutoUpdateEnabled, AutoNavigateNextPage = settings.AutoNavigateNextPage, DefaultSearchQuery = settings.DefaultSearchQuery, FloatingCommentEditor = settings.FloatingCommentEditor, BlockMentionsFromEnemies = settings.BlockMentionsFromEnemies, OnlyAllowDmsFromFriends = settings.OnlyAllowDmsFromFriends, }; } }