namespace ZB.MOM.WW.MxGateway.Server.Configuration;

public sealed class SessionOptions
{
    /// <summary>
    /// Gets the default command timeout in seconds.
    /// </summary>
    public int DefaultCommandTimeoutSeconds { get; init; } = 30;

    /// <summary>
    /// Gets the maximum number of concurrent sessions.
    /// </summary>
    public int MaxSessions { get; init; } = 64;

    /// <summary>
    /// Gets the maximum number of pending commands per session.
    /// </summary>
    public int MaxPendingCommandsPerSession { get; init; } = 128;

    /// <summary>Gets the default session lease duration in seconds.</summary>
    public int DefaultLeaseSeconds { get; init; } = 1800;

    /// <summary>Gets the interval for sweeping expired session leases in seconds.</summary>
    public int LeaseSweepIntervalSeconds { get; init; } = 30;

    /// <summary>
    ///     Gets the detach-grace retention window, in seconds, that a session is kept alive
    ///     after its last external (gRPC) event-stream subscriber drops, so a client can
    ///     reconnect to it. While within the window the session stays in
    ///     <c>Ready</c> and remains usable; if no new external subscriber attaches before the
    ///     window elapses, the lease monitor closes the session exactly as it closes an
    ///     expired lease. The gateway-owned internal dashboard subscriber does not count as an
    ///     external subscriber, so a session whose only remaining subscriber is the dashboard
    ///     mirror still enters detach-grace. A value of <c>0</c> disables retention: the
    ///     session reverts to the original behavior of lingering only until its normal lease
    ///     expires. The reconnect/replay itself is implemented separately; this
    ///     option controls retention and expiry only.
    /// </summary>
    /// <remarks>
    ///     The effective close happens within the next sweep cycle after the window elapses —
    ///     up to <see cref="LeaseSweepIntervalSeconds"/> after expiry. Operators who want a
    ///     firm minimum bound should set <c>DetachGraceSeconds</c> greater than
    ///     <see cref="LeaseSweepIntervalSeconds"/>; otherwise a session whose window expires
    ///     just before a sweep run may be closed within seconds of detach.
    /// </remarks>
    public int DetachGraceSeconds { get; init; } = 30;

    /// <summary>
    ///     Gets the grace period, in seconds, that a faulted session is retained before the
    ///     lease monitor reaps it (killing its worker and freeing the session slot). A faulted
    ///     session is otherwise permanently unusable — every command fails the readiness check —
    ///     yet without this sweep it pins a session slot and a live x86 worker until its normal
    ///     lease expires (up to <see cref="DefaultLeaseSeconds"/>). A value of <c>0</c> (the
    ///     default) reaps a faulted session on the next sweep cycle, bounding the blast radius; a
    ///     positive value keeps the faulted session observable via <c>GetSessionStatus</c> for the
    ///     grace window before it is reclaimed. Must be greater than or equal to zero.
    /// </summary>
    public int FaultedGraceSeconds { get; init; }

    /// <summary>
    /// Gets a value indicating whether multiple event subscribers are allowed per session.
    /// </summary>
    public bool AllowMultipleEventSubscribers { get; init; }

    /// <summary>
    /// Gets the maximum number of concurrent event subscribers per session.
    /// Applies when <see cref="AllowMultipleEventSubscribers"/> is <see langword="true"/>;
    /// effectively 1 when it is <see langword="false"/>. Must be greater than zero.
    /// </summary>
    public int MaxEventSubscribersPerSession { get; init; } = 8;

    /// <summary>
    ///     Gets the bounded time, in milliseconds, the gateway will wait for a worker client
    ///     to reach <c>Ready</c> when the session itself is already <c>Ready</c> but the worker
    ///     state has transiently diverged (e.g. <c>Handshaking</c> after a heartbeat blip).
    ///     The wait applies only to transient worker states; terminal states
    ///     (<c>Faulted</c>/<c>Closing</c>/<c>Closed</c>/no worker) fail fast immediately.
    ///     A value of <c>0</c> (the default) disables the wait — the gateway keeps the original
    ///     fail-fast behavior. Must be greater than or equal to zero.
    /// </summary>
    public int WorkerReadyWaitTimeoutMs { get; init; }
}
