namespace ZB.MOM.WW.ScadaBridge.StoreAndForward;

/// <summary>
/// Configuration options for the Store-and-Forward Engine.
/// </summary>
public class StoreAndForwardOptions
{
    /// <summary>
    /// Path to the legacy standalone store-and-forward SQLite file. <b>Migration-only.</b>
    /// The buffer itself lives in the consolidated LocalDb database (<c>LocalDb:Path</c>)
    /// as of LocalDb Phase 2; this path is read once at boot by
    /// <c>SiteLocalDbLegacyMigrator</c> to drain a pre-Phase-2 file, and is otherwise
    /// unused. A node that has already migrated may leave it set or unset.
    /// </summary>
    public string SqliteDbPath { get; set; } = "./data/store-and-forward.db";

    /// <summary>Default retry interval for messages without per-source settings.</summary>
    public TimeSpan DefaultRetryInterval { get; set; } = TimeSpan.FromSeconds(30);

    /// <summary>
    /// Default maximum retry count before parking. Applied when an
    /// <c>EnqueueAsync</c> caller does not pass an explicit <c>maxRetries</c>.
    /// </summary>
    public int DefaultMaxRetries { get; set; } = 50;

    /// <summary>Interval for the background retry timer sweep.</summary>
    public TimeSpan RetryTimerInterval { get; set; } = TimeSpan.FromSeconds(10);

    /// <summary>
    /// Maximum due rows loaded per retry sweep. Bounds sweep memory and duration
    /// under backlog; the remainder is picked up on the next tick (10 s).
    /// 0 = unlimited (legacy).
    /// </summary>
    public int SweepBatchLimit { get; set; } = 500;

    /// <summary>
    /// Max <c>(category, target)</c> lanes delivered concurrently per sweep.
    /// 1 = legacy serial. Within a lane delivery stays sequential (per-target FIFO).
    /// </summary>
    public int SweepTargetParallelism { get; set; } = 4;

    /// <summary>
    /// WP2.6c (arch-review misc — unbounded S&amp;F observer queue): capacity of the
    /// cached-call audit-observer pump's queue. It was the one unbounded
    /// <c>Channel&lt;T&gt;</c> left in the system — a slow/stuck
    /// <c>ICachedCallLifecycleObserver</c> (a SQLite audit write) could not stretch
    /// the retry sweep, but nothing stopped it growing without bound while the sweep kept
    /// posting. Bounded with <see cref="System.Threading.Channels.BoundedChannelFullMode.DropOldest"/>
    /// — the same overflow policy as its sibling bounded channels
    /// (<c>SiteEventLogger</c>'s write queue, the debug/alarm stream hubs) — so a stuck
    /// observer sheds the oldest unprocessed notifications instead of leaking memory; drops
    /// are counted (see <c>StoreAndForwardService.ObserverQueueDroppedCount</c>).
    /// </summary>
    public int ObserverQueueCapacity { get; set; } = 10_000;
}
