namespace Mbproxy.Options;

public sealed class ResilienceOptions
{
    public RetryProfile BackendConnect { get; init; } = new() { MaxAttempts = 3, BackoffMs = [100, 500, 2000] };
    public RecoveryProfile ListenerRecovery { get; init; } = new()
    {
        InitialBackoffMs = [1000, 2000, 5000, 15000, 30000],
        SteadyStateMs = 30000,
    };

    /// <summary>
    /// In-flight read coalescing options. Defaults to enabled with a 32-party cap so
    /// unconfigured deployments get the de-duplication benefit immediately.
    /// </summary>
    public ReadCoalescingOptions ReadCoalescing { get; init; } = new();
}

public sealed class RetryProfile
{
    public int MaxAttempts { get; init; }
    public IReadOnlyList<int> BackoffMs { get; init; } = [];
}

public sealed class RecoveryProfile
{
    public IReadOnlyList<int> InitialBackoffMs { get; init; } = [];
    public int SteadyStateMs { get; init; }
}

/// <summary>
/// Knobs for the in-flight read-coalescing feature. The feature attaches late-arriving
/// FC03/FC04 reads of identical <c>(unitId, fc, start, qty)</c> tuples to an already-
/// in-flight peer, fanning out the single backend response to every attached upstream
/// client.
///
/// <para>Zero post-response staleness — coalescing operates entirely within the in-flight
/// window (microseconds to ~10 ms typical). Once the response is delivered, the coalescing
/// entry dies.</para>
/// </summary>
public sealed class ReadCoalescingOptions
{
    /// <summary>
    /// Master switch. When <c>false</c>, every FC03/FC04 request allocates a fresh
    /// proxy TxId and round-trips to the backend without attempting to coalesce.
    /// Hot-reloadable via <c>IOptionsMonitor</c>; flipping to <c>false</c> at runtime
    /// does not disturb already-coalesced entries — they drain naturally.
    /// </summary>
    public bool Enabled { get; init; } = true;

    /// <summary>
    /// Per-entry cap on the number of interested parties that may attach to a single
    /// in-flight request. Past this cap, the next identical request opens a fresh
    /// in-flight entry (a fresh backend round-trip). Bounds the response-fanout cost at
    /// O(MaxParties) per entry.
    /// </summary>
    public int MaxParties { get; init; } = 32;
}
