namespace DodoSSH.Client.Terminal;

/// <summary>
/// Somewhere to record that a connection happened, and how long it lasted.
/// </summary>
/// <remarks>
/// <para>
/// <b>Declared here and implemented two layers up.</b> <c>DodoSSH.Client.Terminal</c> references only
/// <c>DodoSSH.Client.Ssh</c> and cannot see the sync layer at all — which is deliberate, because the
/// workspace has to keep running with the vault locked and a direct dependency would invite the opposite.
/// So this is the shape of the hole, and <c>ConnectionRecorder</c> in <c>DodoSSH.Client.Session</c> is what
/// fills it.
/// </para>
/// <para>
/// <b>Both methods return <see langword="void"/> by contract.</b> <see cref="Closed"/>'s only caller is a
/// <c>finally</c> unwinding on a thread-pool thread as a session tears down — including inside the loop that
/// runs when the application is closing — and an encrypt-and-write there is how shutting down comes to take
/// four seconds per open tab. An implementation must hand the work to something else and return.
/// </para>
/// <para>
/// A null sink is a workspace that records nothing, which is what every test and every not-yet-unlocked
/// process has.
/// </para>
/// </remarks>
public interface IConnectionLogSink
{
    /// <summary>
    /// Notes that a connection has opened.
    /// </summary>
    /// <param name="sessionId">The session, as the workspace knows it.</param>
    /// <param name="address">The address as dialled.</param>
    /// <param name="startedAt">When it opened.</param>
    /// <remarks>
    /// Called only after the connection has genuinely been made, so a host-key refusal never arrives here as
    /// a session that started. Those are recorded separately, by the code that holds the typed exception.
    /// </remarks>
    void Opened(uint sessionId, string address, DateTimeOffset startedAt);

    /// <summary>
    /// Notes that the connection has ended, whatever ended it.
    /// </summary>
    /// <param name="sessionId">The session that has ended.</param>
    /// <param name="endedAt">When it ended.</param>
    /// <remarks>
    /// One method for a tab close, a remote hangup and a process shutdown, because all three funnel through
    /// the same <c>finally</c> — and because the difference between them is not something this client can
    /// establish honestly. A session id that was never opened, or has already been closed out, is ignored.
    /// </remarks>
    void Closed(uint sessionId, DateTimeOffset endedAt);
}
