using Microsoft.AspNetCore.SignalR;

namespace Mbproxy.Admin;

/// <summary>
/// The outbound side of the admin live feed. Defined as an interface so
/// <see cref="StatusBroadcaster"/>'s loop logic (snapshot building, group selection,
/// disarm-on-stop) is unit-testable without standing up a SignalR host — tests inject
/// a recording fake; production uses <see cref="SignalRStatusPushSink"/>.
/// </summary>
internal interface IStatusPushSink
{
    /// <summary>Pushes a fleet snapshot to every fleet-dashboard subscriber.</summary>
    Task PushFleetAsync(StatusResponse snapshot, CancellationToken ct);

    /// <summary>Pushes one PLC's detail payload to that PLC's detail-page subscribers.</summary>
    Task PushPlcAsync(string plcName, PlcDetailResponse detail, CancellationToken ct);
}

/// <summary>
/// Production <see cref="IStatusPushSink"/> — forwards pushes onto the SignalR
/// <see cref="StatusHub"/> groups via <see cref="IHubContext{THub}"/>.
/// </summary>
internal sealed class SignalRStatusPushSink : IStatusPushSink
{
    private readonly IHubContext<StatusHub> _hub;

    public SignalRStatusPushSink(IHubContext<StatusHub> hub) => _hub = hub;

    public Task PushFleetAsync(StatusResponse snapshot, CancellationToken ct)
        => _hub.Clients.Group(StatusHub.FleetGroup).SendAsync("fleet", snapshot, ct);

    public Task PushPlcAsync(string plcName, PlcDetailResponse detail, CancellationToken ct)
        => _hub.Clients.Group(StatusHub.PlcGroup(plcName)).SendAsync("plc", detail, ct);
}
