using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.SignalR.Client;
using ZB.MOM.WW.MxGateway.Server.Dashboard.Hubs;

namespace ZB.MOM.WW.MxGateway.Server.Dashboard.Components;

/// <summary>
/// Base class for Blazor dashboard pages that watch gateway metrics
/// snapshots. The previous implementation polled
/// <see cref="IDashboardSnapshotService.WatchSnapshotsAsync"/> directly; we
/// now subscribe to <see cref="DashboardSnapshotHub"/> so updates are
/// pushed and disconnects survive reconnects via SignalR's
/// auto-reconnect.
/// </summary>
public abstract class DashboardPageBase : ComponentBase, IAsyncDisposable
{
    private HubConnection? _hub;

    /// <summary>Snapshot service used to seed the initial render before the hub connects.</summary>
    [Inject]
    protected IDashboardSnapshotService SnapshotService { get; set; } = null!;

    /// <summary>Factory that builds the SignalR connection (mints the hub bearer token).</summary>
    [Inject]
    protected DashboardHubConnectionFactory HubFactory { get; set; } = null!;

    /// <summary>
    /// The most recent gateway metric snapshot. Synchronously seeded from
    /// <see cref="IDashboardSnapshotService.GetSnapshot"/> for the very
    /// first render, then refreshed by hub push.
    /// </summary>
    protected DashboardSnapshot? Snapshot { get; private set; }

    /// <inheritdoc />
    protected override async Task OnInitializedAsync()
    {
        Snapshot = SnapshotService.GetSnapshot();
        await ConnectHubAsync().ConfigureAwait(false);
    }

    /// <inheritdoc />
    public async ValueTask DisposeAsync()
    {
        if (_hub is not null)
        {
            try
            {
                await _hub.DisposeAsync().ConfigureAwait(false);
            }
            catch
            {
                // Disposal-time errors are best-effort.
            }
        }

        GC.SuppressFinalize(this);
    }

    private async Task ConnectHubAsync()
    {
        _hub = HubFactory.Create("/hubs/snapshot");
        _hub.On<DashboardSnapshot>(DashboardSnapshotHub.SnapshotMessage, async snapshot =>
        {
            Snapshot = snapshot;
            await InvokeAsync(StateHasChanged).ConfigureAwait(false);
        });

        try
        {
            await _hub.StartAsync().ConfigureAwait(false);
        }
        catch
        {
            // Hub is best-effort; the initial GetSnapshot() seed remains
            // valid and the snapshot service keeps populating its cache for
            // the next reconnect cycle.
        }
    }
}
