using ZB.MOM.WW.OtOpcUa.Commons.Messages.Drivers;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Hubs;

/// <summary>
///     Singleton last-snapshot-per-instance cache. Populated by
///     <c>DriverStatusSignalRBridge</c> as it forwards DPS messages; read by
///     <see cref="DriverStatusHub.JoinDriver"/> so newly-joined clients see current state
///     without waiting for the next change event, and subscribed to directly by the Blazor
///     Server <c>DriverStatusPanel</c> via <see cref="SnapshotChanged"/>.
/// </summary>
public interface IDriverStatusSnapshotStore
{
    /// <summary>Stores or replaces the last-known health snapshot for a driver instance.</summary>
    /// <param name="snapshot">The driver health snapshot to store.</param>
    void Upsert(DriverHealthChanged snapshot);

    /// <summary>Attempts to retrieve the last-known health snapshot for a driver instance.</summary>
    /// <param name="driverInstanceId">The driver instance's stable logical ID.</param>
    /// <param name="snapshot">The stored snapshot, if found.</param>
    /// <returns><see langword="true"/> if a snapshot was found; otherwise <see langword="false"/>.</returns>
    bool TryGet(string driverInstanceId, out DriverHealthChanged snapshot);

    /// <summary>Returns a point-in-time snapshot of every driver instance's last-known health.</summary>
    /// <returns>A read-only collection of the last-known health snapshot for each driver instance.</returns>
    IReadOnlyCollection<DriverHealthChanged> GetAll();

    /// <summary>
    ///     Raised after every <see cref="Upsert"/> with the just-stored snapshot. Lets in-process
    ///     consumers (the Blazor Server <c>DriverStatusPanel</c>) receive live updates by reading
    ///     this singleton directly instead of opening a self-targeted SignalR connection — which a
    ///     server-side Blazor component cannot reach when the public URL (e.g. a reverse-proxy port)
    ///     differs from the local Kestrel bind. Handlers run on the caller's thread (the bridge
    ///     actor), so subscribers must marshal to their own sync context.
    /// </summary>
    event Action<DriverHealthChanged>? SnapshotChanged;
}
