namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;

/// <summary>
///     Optional composable driver capability: the driver consumes <b>other</b> tags' live values.
///     The host registers the declared <see cref="DependencyRefs"/> with its per-node dependency mux
///     and forwards every matching value change into <see cref="OnDependencyValue"/> — the seam that
///     lets a host-blind driver (e.g. the <c>Calculation</c> pseudo-driver) read the address space's
///     live values without any cross-driver plumbing of its own.
/// </summary>
/// <remarks>
///     <para>
///         The mechanism mirrors how a <c>VirtualTagActor</c> registers interest on the
///         <c>DependencyMuxActor</c>: the mux already receives every driver's
///         <c>AttributeValuePublished</c> keyed by wire-ref (under v3, RawPath), so a driver that
///         implements this interface simply piggy-backs on that fan-out. A calc tag's computed output
///         re-enters the mux via the ordinary driver publish path, so calc-of-calc chains work with no
///         extra machinery — which is exactly why the deploy-time cycle gate is mandatory.
///     </para>
///     <para>
///         Implementations of <see cref="OnDependencyValue"/> are invoked from an actor context and
///         <b>must be non-blocking</b> — do the work inline and cheaply (the compile cache makes
///         steady-state calc evaluation a bounded method invocation), never block on I/O.
///     </para>
/// </remarks>
public interface IDependencyConsumer
{
    /// <summary>
    ///     Wire-refs (RawPaths) this driver needs fed to it, derived from its authored tags. The host
    ///     re-reads this after <see cref="IDriver.InitializeAsync"/> / <see cref="IDriver.ReinitializeAsync"/>
    ///     and (re)registers the set with its dependency mux on every apply, so a tag/script edit that
    ///     changes the set converges without a bespoke notification.
    /// </summary>
    IReadOnlyCollection<string> DependencyRefs { get; }

    /// <summary>
    ///     Host push of a single dependency value change. Called from an actor context, so the
    ///     implementation must be non-blocking.
    /// </summary>
    /// <param name="rawPath">The changed dependency's wire-ref (RawPath).</param>
    /// <param name="value">The new value (may be null).</param>
    /// <param name="statusCode">The OPC UA status code carried with the value (0 = Good).</param>
    /// <param name="timestampUtc">The source timestamp of the change.</param>
    void OnDependencyValue(string rawPath, object? value, uint statusCode, DateTime timestampUtc);
}
