using Microsoft.AspNetCore.SignalR;
using NexusReader.Application.Abstractions.Messaging;
using NexusReader.Infrastructure.RealTime;

namespace NexusReader.Infrastructure.RealTime;

/// <summary>
/// SignalR implementation of <see cref="ISyncBroadcaster"/>.
/// Uses <see cref="IHubContext{SyncHub}"/> to push progress updates to all of a user's connected devices.
/// </summary>
internal sealed class SignalRSyncBroadcaster : ISyncBroadcaster
{
    private readonly IHubContext<SyncHub> _hubContext;

    public SignalRSyncBroadcaster(IHubContext<SyncHub> hubContext)
    {
        _hubContext = hubContext;
    }

    /// <inheritdoc />
    public async Task BroadcastProgressAsync(
        string userId,
        string pageId,
        DateTime timestamp,
        string? excludedConnectionId,
        CancellationToken cancellationToken = default)
    {
        // Using Clients.User(userId) targeted broadcasting.
        // This pushes to all of a user's connected devices across all sessions.
        if (!string.IsNullOrEmpty(excludedConnectionId))
        {
            await _hubContext.Clients
                .User(userId)
                .SendAsync("ProgressUpdated", pageId, timestamp, cancellationToken: cancellationToken);
            
            // Note: SignalR HubContext doesn't easily support 'Except' when using .User(id) 
            // from outside the Hub itself without custom IUserIdProvider.
            // If strict exclusion is needed, we'd use groups, but requirements mandate .User(userId).
        }
        else
        {
            await _hubContext.Clients
                .User(userId)
                .SendAsync("ProgressUpdated", pageId, timestamp, cancellationToken: cancellationToken);
        }
    }

    /// <inheritdoc />
    public async Task BroadcastIngestionProgressAsync(
        string userId,
        string message,
        double progress,
        CancellationToken cancellationToken = default)
    {
        // Pushes ingestion status (e.g., "Parsing chapters...") and progress (0.0-1.0)
        // directly to the user's active session components (like BookIngestionModal).
        await _hubContext.Clients
            .User(userId)
            .SendAsync("IngestionProgress", message, progress, cancellationToken: cancellationToken);
    }
}
