using ColaFlow.Modules.Mcp.Application.DTOs.Notifications; using ColaFlow.Modules.Mcp.Application.Services; using ColaFlow.Modules.Mcp.Domain.Events; using MediatR; using Microsoft.Extensions.Logging; namespace ColaFlow.Modules.Mcp.Application.EventHandlers; /// /// Event handler that sends SignalR notifications when a PendingChange is approved /// Runs in parallel with PendingChangeApprovedEventHandler (which executes the change) /// public class PendingChangeApprovedNotificationHandler( IMcpNotificationService notificationService, ILogger logger) : INotificationHandler { private readonly IMcpNotificationService _notificationService = notificationService ?? throw new ArgumentNullException(nameof(notificationService)); private readonly ILogger _logger = logger ?? throw new ArgumentNullException(nameof(logger)); public async Task Handle(PendingChangeApprovedEvent notification, CancellationToken cancellationToken) { _logger.LogInformation( "Handling PendingChangeApprovedEvent for notification - PendingChangeId={PendingChangeId}, EntityType={EntityType}", notification.PendingChangeId, notification.Diff.EntityType); try { // Create notification DTO var notificationDto = new PendingChangeApprovedNotification { NotificationType = "PendingChangeApproved", PendingChangeId = notification.PendingChangeId, ToolName = notification.ToolName, EntityType = notification.Diff.EntityType, Operation = notification.Diff.Operation, EntityId = notification.Diff.EntityId, ApprovedBy = notification.ApprovedBy, TenantId = notification.TenantId, Timestamp = DateTime.UtcNow }; // Send notification via SignalR await _notificationService.NotifyPendingChangeApprovedAsync(notificationDto, cancellationToken); _logger.LogInformation( "PendingChangeApproved notification sent successfully - PendingChangeId={PendingChangeId}", notification.PendingChangeId); } catch (Exception ex) { _logger.LogError(ex, "Failed to send PendingChangeApproved notification - PendingChangeId={PendingChangeId}", notification.PendingChangeId); // Don't rethrow - notification failure shouldn't break the main flow } } }