namespace ZB.MOM.WW.Audit;

/// <summary>Fans an event out to several writers. Best-effort: a failing writer does not stop the others.</summary>
/// <remarks>Every inner-writer failure is swallowed — including <see cref="OperationCanceledException"/>
/// — so the fan-out drains and the caller is never aborted, honoring the <see cref="IAuditWriter"/>
/// "must not throw to the caller" contract even when a request-scoped cancellation token is passed.</remarks>
public sealed class CompositeAuditWriter : IAuditWriter
{
    private readonly IReadOnlyList<IAuditWriter> _inner;

    /// <summary>Creates a composite over the given writers.</summary>
    public CompositeAuditWriter(IEnumerable<IAuditWriter> inner)
    {
        ArgumentNullException.ThrowIfNull(inner);
        _inner = inner.ToArray();
    }

    /// <inheritdoc />
    public async Task WriteAsync(AuditEvent evt, CancellationToken ct = default)
    {
        ArgumentNullException.ThrowIfNull(evt);
        foreach (var writer in _inner)
        {
            try { await writer.WriteAsync(evt, ct).ConfigureAwait(false); }
            catch { /* best-effort seam: a failing writer (incl. cancellation) must not stop the others or the caller */ }
        }
    }
}
