using ColaFlow.Modules.Mcp.Application.DTOs.Notifications; using ColaFlow.Modules.Mcp.Application.Services; using ColaFlow.Modules.Mcp.Infrastructure.Hubs; using Microsoft.AspNetCore.SignalR; using Microsoft.Extensions.Logging; namespace ColaFlow.Modules.Mcp.Infrastructure.Services; /// /// Implementation of IMcpNotificationService using SignalR /// public class McpNotificationService : IMcpNotificationService { private readonly IHubContext _hubContext; private readonly ILogger _logger; public McpNotificationService( IHubContext hubContext, ILogger logger) { _hubContext = hubContext ?? throw new ArgumentNullException(nameof(hubContext)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public async Task NotifyPendingChangeCreatedAsync( PendingChangeCreatedNotification notification, CancellationToken cancellationToken = default) { var groupName = GetPendingChangeGroupName(notification.PendingChangeId); var tenantGroupName = GetTenantGroupName(notification.TenantId); _logger.LogInformation( "Sending PendingChangeCreated notification - PendingChangeId={PendingChangeId}, EntityType={EntityType}, Operation={Operation}", notification.PendingChangeId, notification.EntityType, notification.Operation); // Send to both: specific pending change subscribers AND all tenant members await _hubContext.Clients .Groups(groupName, tenantGroupName) .SendAsync("PendingChangeCreated", notification, cancellationToken); _logger.LogDebug( "PendingChangeCreated notification sent - Groups=[{GroupName}, {TenantGroupName}]", groupName, tenantGroupName); } public async Task NotifyPendingChangeApprovedAsync( PendingChangeApprovedNotification notification, CancellationToken cancellationToken = default) { var groupName = GetPendingChangeGroupName(notification.PendingChangeId); var tenantGroupName = GetTenantGroupName(notification.TenantId); _logger.LogInformation( "Sending PendingChangeApproved notification - PendingChangeId={PendingChangeId}, EntityType={EntityType}, ApprovedBy={ApprovedBy}", notification.PendingChangeId, notification.EntityType, notification.ApprovedBy); await _hubContext.Clients .Groups(groupName, tenantGroupName) .SendAsync("PendingChangeApproved", notification, cancellationToken); _logger.LogDebug( "PendingChangeApproved notification sent - Groups=[{GroupName}, {TenantGroupName}]", groupName, tenantGroupName); } public async Task NotifyPendingChangeRejectedAsync( PendingChangeRejectedNotification notification, CancellationToken cancellationToken = default) { var groupName = GetPendingChangeGroupName(notification.PendingChangeId); var tenantGroupName = GetTenantGroupName(notification.TenantId); _logger.LogInformation( "Sending PendingChangeRejected notification - PendingChangeId={PendingChangeId}, Reason={Reason}, RejectedBy={RejectedBy}", notification.PendingChangeId, notification.Reason, notification.RejectedBy); await _hubContext.Clients .Groups(groupName, tenantGroupName) .SendAsync("PendingChangeRejected", notification, cancellationToken); _logger.LogDebug( "PendingChangeRejected notification sent - Groups=[{GroupName}, {TenantGroupName}]", groupName, tenantGroupName); } public async Task NotifyPendingChangeAppliedAsync( PendingChangeAppliedNotification notification, CancellationToken cancellationToken = default) { var groupName = GetPendingChangeGroupName(notification.PendingChangeId); var tenantGroupName = GetTenantGroupName(notification.TenantId); _logger.LogInformation( "Sending PendingChangeApplied notification - PendingChangeId={PendingChangeId}, Result={Result}", notification.PendingChangeId, notification.Result); await _hubContext.Clients .Groups(groupName, tenantGroupName) .SendAsync("PendingChangeApplied", notification, cancellationToken); _logger.LogDebug( "PendingChangeApplied notification sent - Groups=[{GroupName}, {TenantGroupName}]", groupName, tenantGroupName); } public async Task NotifyPendingChangeExpiredAsync( PendingChangeExpiredNotification notification, CancellationToken cancellationToken = default) { var groupName = GetPendingChangeGroupName(notification.PendingChangeId); var tenantGroupName = GetTenantGroupName(notification.TenantId); _logger.LogInformation( "Sending PendingChangeExpired notification - PendingChangeId={PendingChangeId}, ExpiredAt={ExpiredAt}", notification.PendingChangeId, notification.ExpiredAt); await _hubContext.Clients .Groups(groupName, tenantGroupName) .SendAsync("PendingChangeExpired", notification, cancellationToken); _logger.LogDebug( "PendingChangeExpired notification sent - Groups=[{GroupName}, {TenantGroupName}]", groupName, tenantGroupName); } private static string GetPendingChangeGroupName(Guid pendingChangeId) { return $"pending-change-{pendingChangeId}"; } private static string GetTenantGroupName(Guid tenantId) { return $"tenant-{tenantId}"; } }