using Govor.Application.Interfaces; using Govor.Domain.Models.Messages; using Govor.Domain; using Govor.Domain.Common; using Microsoft.EntityFrameworkCore; using SmartRes; namespace Govor.Application.Messages; public class MessagesLoader : IMessagesLoader { private readonly GovorDbContext _dbContext; public MessagesLoader(GovorDbContext dbContext) { _dbContext = dbContext; } public async Task,Error>> LoadMessagesInUserChat( Guid privateChatId, Guid currentUser, Guid? startMessageId, int before = 20, int after = 2) { if (privateChatId == Guid.Empty) return Result.Failure>(Error.Failure(nameof(ArgumentException),"PrivateChatId id cannot be empty.")); var chatExists = await _dbContext.PrivateChats.AnyAsync(c => c.Id == privateChatId); if (!chatExists) return new List(0); var query = _dbContext.Messages .AsNoTracking() .Include(m => m.MediaAttachments) .ThenInclude(m => m.MediaFile) .Where(m => m.RecipientType == RecipientType.User && m.RecipientId == privateChatId); return await FetchPaginatedMessagesAsync(query, startMessageId, before, after); } public async Task,Error>> LoadMessagesInChatGroup( Guid chatId, Guid currentUser, Guid? startMessageId, int before = 20, int after = 2) { if (chatId == Guid.Empty) return Result.Failure>(Error.Failure(nameof(ArgumentException),"Chat id cannot be empty.")); var isMember = await _dbContext.GroupMemberships .AnyAsync(gm => gm.UserId == currentUser && gm.GroupId == chatId); if (!isMember) return new List(0); var query = _dbContext.Messages .AsNoTracking() .Include(m => m.MediaAttachments) .ThenInclude(m => m.MediaFile) .AsSplitQuery() .Where(m => m.RecipientType == RecipientType.Group && m.RecipientId == chatId); return await FetchPaginatedMessagesAsync(query, startMessageId, before, after); } private static async Task> FetchPaginatedMessagesAsync( IQueryable baseQuery, Guid? startMessageId, int before, int after) { if (startMessageId is null) { return await baseQuery .OrderByDescending(m => m.SentAt) .Take(before) .OrderBy(m => m.SentAt) .ToListAsync(); } var startMessage = await baseQuery.FirstOrDefaultAsync(m => m.Id == startMessageId.Value); if (startMessage == null) return []; var beforeMessages = await baseQuery .Where(m => m.SentAt < startMessage.SentAt) .OrderByDescending(m => m.SentAt) .Take(before) .ToListAsync(); var afterMessages = await baseQuery .Where(m => m.SentAt > startMessage.SentAt) .OrderBy(m => m.SentAt) .Take(after) .ToListAsync(); beforeMessages.Reverse(); var result = new List(beforeMessages.Count + 1 + afterMessages.Count); result.AddRange(beforeMessages); result.Add(startMessage); result.AddRange(afterMessages); return result; } }