using Akka.Actor;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;

namespace ZB.MOM.WW.OtOpcUa.Runtime.Historian;

/// <summary>
///     <see cref="IHistorizedTagSubscriptionSink"/> adapter that bridges the address-space applier (in
///     the OpcUaServer layer) to the <see cref="ContinuousHistorizationRecorder"/> actor in Runtime —
///     keeping the applier free of any actor/Runtime dependency (it sees only the abstraction). Each
///     feed is a single non-blocking <see cref="ICanTell.Tell"/> (a fire-and-forget mailbox post), so it
///     never blocks the OPC UA publish thread the applier runs on; the recorder converges its mux
///     interest from the delta off the actor thread.
/// </summary>
public sealed class ActorHistorizedTagSubscriptionSink : IHistorizedTagSubscriptionSink
{
    private readonly IActorRef _recorder;

    /// <summary>Initializes a new instance of the <see cref="ActorHistorizedTagSubscriptionSink"/> class.</summary>
    /// <param name="recorder">The continuous-historization recorder actor to feed historized-ref deltas to.</param>
    public ActorHistorizedTagSubscriptionSink(IActorRef recorder)
    {
        ArgumentNullException.ThrowIfNull(recorder);
        _recorder = recorder;
    }

    /// <inheritdoc />
    public void UpdateHistorizedRefs(IReadOnlyList<HistorizedTagRef> added, IReadOnlyList<HistorizedTagRef> removed)
    {
        ArgumentNullException.ThrowIfNull(added);
        ArgumentNullException.ThrowIfNull(removed);

        if (added.Count == 0 && removed.Count == 0)
        {
            // Nothing to converge — skip the mailbox post entirely.
            return;
        }

        _recorder.Tell(new ContinuousHistorizationRecorder.UpdateHistorizedRefs(added, removed));
    }
}
