using System.Runtime.CompilerServices;
using ZB.MOM.WW.MxGateway.Contracts.Proto;

namespace ZB.MOM.WW.MxGateway.Client;

/// <summary>
/// Extension methods that project a raw <see cref="MxEvent"/> stream into the
/// typed <see cref="MxEventStreamItem"/> surface, making the gateway's
/// reconnect-replay gap sentinel observable.
/// </summary>
public static class MxEventStreamExtensions
{
    /// <summary>
    /// Projects a raw <see cref="MxEvent"/> stream (e.g.
    /// <see cref="MxGatewaySession.StreamEventsAsync"/> or
    /// <see cref="MxGatewayClient.StreamEventsAsync"/>) into typed
    /// <see cref="MxEventStreamItem"/> values. Normal events pass through with
    /// <see cref="MxEventStreamItem.IsReplayGap"/> false; the gateway's
    /// reconnect-replay gap sentinel is surfaced with
    /// <see cref="MxEventStreamItem.IsReplayGap"/> true and
    /// <see cref="MxEventStreamItem.ReplayGap"/> populated. The stream is
    /// forwarded faithfully — no event is synthesized or dropped.
    /// </summary>
    /// <param name="source">The raw event stream to wrap.</param>
    /// <param name="cancellationToken">Cancellation token for the enumeration.</param>
    /// <returns>The same events, each wrapped as an <see cref="MxEventStreamItem"/>.</returns>
    public static async IAsyncEnumerable<MxEventStreamItem> AsStreamItemsAsync(
        this IAsyncEnumerable<MxEvent> source,
        [EnumeratorCancellation] CancellationToken cancellationToken = default)
    {
        ArgumentNullException.ThrowIfNull(source);

        await foreach (MxEvent gatewayEvent in source
            .WithCancellation(cancellationToken)
            .ConfigureAwait(false))
        {
            yield return MxEventStreamItem.From(gatewayEvent);
        }
    }
}
