using System.Security.Claims;

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

/// <summary>
/// Dashboard surface for the destructive session-management actions —
/// Close (graceful shutdown) and Kill (force-terminate) — exposed by the
/// Admin role.
/// </summary>
/// <remarks>
///     The dashboard binds the destructive Close/Kill UI to this service so
///     the underlying <see cref="Sessions.ISessionManager"/> calls flow through
///     a single audited and role-gated entry point. All operations are gated
///     by <see cref="CanManage"/>; non-Admin callers are rejected with a
///     <c>Succeeded = false</c> result rather than throwing. Missing sessions
///     also surface as <see cref="DashboardSessionAdminResult.Fail(string)"/> so
///     Razor pages can render the message without an error boundary. Each
///     successful call is logged at Information including the acting user
///     (from <see cref="ClaimsPrincipal.Identity"/>'s name) and the remote
///     address resolved from <see cref="IHttpContextAccessor"/>.
/// </remarks>
public interface IDashboardSessionAdminService
{
    /// <summary>
    /// Returns whether the given principal is authorized to perform
    /// destructive session-management actions.
    /// </summary>
    /// <remarks>
    ///     Requires <see cref="System.Security.Principal.IIdentity.IsAuthenticated"/>
    ///     to be true and membership in the
    ///     <see cref="DashboardRoles.Admin"/> role. Pages typically gate the
    ///     Close/Kill buttons on this value at render time so non-Admin
    ///     viewers never see them.
    /// </remarks>
    /// <param name="user">Caller principal.</param>
    /// <returns><c>true</c> when the caller may close or kill sessions; otherwise <c>false</c>.</returns>
    bool CanManage(ClaimsPrincipal user);

    /// <summary>
    /// Closes the given session gracefully (worker is given the configured
    /// shutdown grace period before being terminated).
    /// </summary>
    /// <remarks>
    ///     Returns <see cref="DashboardSessionAdminResult.Fail(string)"/>
    ///     when the caller is not Admin, when the session id is blank, or when
    ///     <see cref="Sessions.ISessionManager.CloseSessionAsync"/> raises a
    ///     <see cref="Sessions.SessionManagerException"/> (including the
    ///     <see cref="Sessions.SessionManagerErrorCode.SessionNotFound"/>
    ///     case). Successful closes are audit-logged with the caller name,
    ///     session id, and remote address.
    /// </remarks>
    /// <param name="user">Caller principal.</param>
    /// <param name="sessionId">Session identifier to close.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>Result describing success/failure and a user-facing message.</returns>
    Task<DashboardSessionAdminResult> CloseSessionAsync(
        ClaimsPrincipal user,
        string sessionId,
        CancellationToken cancellationToken);

    /// <summary>
    /// Force-terminates the worker process backing the given session without
    /// attempting a graceful shutdown.
    /// </summary>
    /// <remarks>
    ///     Invoked from the dashboard Kill button. Uses the
    ///     <c>dashboard-admin-kill</c> reason constant — that string reaches
    ///     the audit log and the <c>mxgateway.workers.killed</c> metric tag.
    ///     Returns <see cref="DashboardSessionAdminResult.Fail(string)"/> for
    ///     non-Admin callers, blank session ids, or any
    ///     <see cref="Sessions.SessionManagerException"/> from the underlying
    ///     manager (the <see cref="Sessions.SessionManagerErrorCode.SessionNotFound"/>
    ///     case is recognized and reported as "not found"). Successful kills
    ///     are audit-logged with the caller name, session id, and remote
    ///     address.
    /// </remarks>
    /// <param name="user">Caller principal.</param>
    /// <param name="sessionId">Session identifier to kill.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>Result describing success/failure and a user-facing message.</returns>
    Task<DashboardSessionAdminResult> KillWorkerAsync(
        ClaimsPrincipal user,
        string sessionId,
        CancellationToken cancellationToken);
}
