using System.Diagnostics.CodeAnalysis;
using ZB.MOM.WW.MxGateway.Contracts.Proto;

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

public interface ISessionManager
{
    /// <summary>Opens a new gateway session and launches a worker process.</summary>
    /// <param name="request">Request payload.</param>
    /// <param name="clientIdentity">Client identity string.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>The newly opened session.</returns>
    Task<GatewaySession> OpenSessionAsync(
        SessionOpenRequest request,
        string? clientIdentity,
        CancellationToken cancellationToken);

    /// <summary>Attempts to retrieve a session by ID.</summary>
    /// <param name="sessionId">Identifier of the session.</param>
    /// <param name="session">The retrieved session, if found.</param>
    /// <returns>True if the session exists; otherwise false.</returns>
    bool TryGetSession(
        string sessionId,
        [MaybeNullWhen(false)] out GatewaySession session);

    /// <summary>Invokes a command on the worker for the specified session.</summary>
    /// <param name="sessionId">Identifier of the session.</param>
    /// <param name="command">Command to invoke.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>The command reply from the worker.</returns>
    Task<WorkerCommandReply> InvokeAsync(
        string sessionId,
        WorkerCommand command,
        CancellationToken cancellationToken);

    /// <summary>Reads events streamed from the worker for the specified session.</summary>
    /// <param name="sessionId">Identifier of the session.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>Events emitted by the worker.</returns>
    IAsyncEnumerable<WorkerEvent> ReadEventsAsync(
        string sessionId,
        CancellationToken cancellationToken);

    /// <summary>Closes a session and terminates its worker process.</summary>
    /// <param name="sessionId">Identifier of the session to close.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>The result of closing the session.</returns>
    Task<SessionCloseResult> CloseSessionAsync(
        string sessionId,
        CancellationToken cancellationToken);

    /// <summary>
    /// Forcefully terminates a session's worker without attempting graceful shutdown,
    /// transitions the session to Closed, and removes it from the registry.
    /// </summary>
    /// <param name="sessionId">Identifier of the session whose worker to kill.</param>
    /// <param name="reason">Reason for killing the worker (recorded in logs/audit).</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>The result of closing the session.</returns>
    Task<SessionCloseResult> KillWorkerAsync(
        string sessionId,
        string reason,
        CancellationToken cancellationToken);

    /// <summary>Closes all sessions with expired leases at the specified time.</summary>
    /// <param name="now">The current time to evaluate expiration against.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>The number of sessions closed.</returns>
    Task<int> CloseExpiredLeasesAsync(
        DateTimeOffset now,
        CancellationToken cancellationToken);

    /// <summary>Shuts down all sessions and the session manager.</summary>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    Task ShutdownAsync(CancellationToken cancellationToken);
}
