namespace Mbproxy.Proxy.Supervision;

/// <summary>
/// State machine states for <see cref="PlcListenerSupervisor"/>.
/// </summary>
public enum SupervisorState
{
    /// <summary>
    /// The listener is bound and its accept loop is running.
    /// Entry conditions: <see cref="PlcListener.StartAsync"/> succeeded (on first attempt or
    /// after a recovery attempt).
    /// </summary>
    Bound,

    /// <summary>
    /// The listener is not bound; the supervisor is waiting for the next Polly retry delay
    /// before reattempting. Entered after any failed bind (at startup or at runtime).
    /// </summary>
    Recovering,

    /// <summary>
    /// Terminal state. <see cref="PlcListenerSupervisor.StopAsync"/> was called; the supervisor
    /// task has been cancelled and will not retry.
    /// </summary>
    Stopped,
}

/// <summary>
/// Immutable point-in-time snapshot of a supervisor's state. Consumed by the status
/// page via <see cref="PlcListenerSupervisor.Snapshot"/>.
///
/// <para><b>RecoveryAttempts semantics</b>: this counter <em>accumulates over the lifetime
/// of the supervisor</em> and is never reset. Operators reading the status page should
/// interpret it as "how many times has this listener faulted or failed to bind since
/// the service started" — useful for detecting port-flapping or repeated OS network
/// resets.</para>
/// </summary>
/// <param name="State">Current state of the supervisor.</param>
/// <param name="LastBindError">
/// Most recent bind failure message (up to 256 chars). <c>null</c> if the listener
/// has never failed to bind.
/// </param>
/// <param name="RecoveryAttempts">
/// Total number of failed bind attempts over the lifetime of this supervisor.
/// Accumulates; never resets to 0.
/// </param>
public sealed record SupervisorSnapshot(
    SupervisorState State,
    string? LastBindError,
    int RecoveryAttempts);
