using Knot.Contracts.Messaging.Application.Abstractions; using Knot.Contracts.Messaging.Domain; using Knot.Shared.Kernel; using MediatR; namespace Knot.Modules.Messaging.Infrastructure.Handlers; public sealed class MessageSentDomainEventHandler : INotificationHandler { private readonly IMessageNotifier _hubContext; private readonly IMessageRepository _messageRepository; private readonly IUserDisplayNameProvider _displayNameProvider; public MessageSentDomainEventHandler( IMessageNotifier hubContext, IMessageRepository messageRepository, IUserDisplayNameProvider displayNameProvider) { _hubContext = hubContext; _messageRepository = messageRepository; _displayNameProvider = displayNameProvider; } public async Task Handle(MessageSentDomainEvent notification, CancellationToken cancellationToken) { var message = await _messageRepository.GetByIdAsync(notification.MessageId, cancellationToken); if (message is null) { return; } var userInfo = await _displayNameProvider.GetUserInfoAsync(message.SenderId, cancellationToken); var senderObj = userInfo != null ? new { Id = userInfo.Id, Username = userInfo.Username, DisplayName = userInfo.DisplayName, Avatar = userInfo.Avatar } : new { Id = message.SenderId, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null }; object? forwardedFromObj = null; if (message.ForwardedFromId.HasValue) { var fwdUserInfo = await _displayNameProvider.GetUserInfoAsync(message.ForwardedFromId.Value, cancellationToken); forwardedFromObj = fwdUserInfo != null ? new { Id = fwdUserInfo.Id, Username = fwdUserInfo.Username, DisplayName = fwdUserInfo.DisplayName, Avatar = fwdUserInfo.Avatar } : new { Id = message.ForwardedFromId.Value, Username = "unknown", DisplayName = "Unknown", Avatar = (string?)null }; } object? replyToObj = null; if (message.ReplyToId.HasValue) { var replyMsg = await _messageRepository.GetByIdAsync(message.ReplyToId.Value, cancellationToken); if (replyMsg != null) { var replySenderInfo = await _displayNameProvider.GetUserInfoAsync(replyMsg.SenderId, cancellationToken); replyToObj = new { Id = replyMsg.Id, Content = replyMsg.Content, Quote = message is TextMessage tm ? tm.Quote : null, media = (replyMsg as MediaMessage)?.Media.Select(rm => new { rm.Type, rm.Url }).ToList() ?? (object)Array.Empty(), Sender = replySenderInfo != null ? new { Id = replySenderInfo.Id, Username = replySenderInfo.Username, DisplayName = replySenderInfo.DisplayName } : new { Id = replyMsg.SenderId, Username = "unknown", DisplayName = "Unknown" } }; } } await _hubContext.NotifyNewMessageAsync(notification.ChatId, new { id = message.Id, chatId = message.ChatId, senderId = message.SenderId, content = message.Content, type = message.Type, createdAt = message.CreatedAt, forwardedFromId = message.ForwardedFromId, forwardedFrom = forwardedFromObj, replyToId = message.ReplyToId, replyTo = replyToObj, quote = message is TextMessage tm2 ? tm2.Quote : null, media = (message as MediaMessage)?.Media.Select(m => new { type = m.Type, url = m.Url, filename = m.FileId, size = m.Size }).ToList() ?? (object)Array.Empty(), sender = senderObj, readBy = new List(), storyId = (message as StoryMessage)?.StoryId, storyMediaUrl = (message as StoryMessage)?.StoryMediaUrl, storyMediaType = (message as StoryMessage)?.StoryMediaType, callType = (message as CallMessage)?.CallType, callStatus = (message as CallMessage)?.CallStatus, duration = (message as CallMessage)?.Duration, pollOptions = (message as PollMessage)?.Options.Select(o => new { id = o.Id, text = o.Text, voteCount = o.VoteCount }).ToList(), pollIsMultipleChoice = (message as PollMessage)?.IsMultipleChoice, pollIsClosed = (message as PollMessage)?.IsClosed, pollIsAnonymous = (message as PollMessage)?.IsAnonymous }, cancellationToken); } }