using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ZB.MOM.WW.MxGateway.Contracts.Proto;
using ZB.MOM.WW.MxGateway.Worker.Sta;

namespace ZB.MOM.WW.MxGateway.Worker.MxAccess;

/// <summary>
/// Manages the runtime session between the worker and the MXAccess COM instance on an STA thread.
/// </summary>
public interface IWorkerRuntimeSession : IDisposable
{
    /// <summary>
    /// Starts the session, creates the MXAccess COM object, and returns ready metadata.
    /// </summary>
    /// <param name="sessionId">Identifier of the session.</param>
    /// <param name="workerProcessId">ID of the worker process.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>Asynchronous task returning worker readiness metadata.</returns>
    Task<WorkerReady> StartAsync(
        string sessionId,
        int workerProcessId,
        CancellationToken cancellationToken = default);

    /// <summary>
    /// Dispatches an STA command to the MXAccess runtime and returns the reply.
    /// </summary>
    /// <param name="command">STA command to execute on the STA thread.</param>
    /// <returns>Asynchronous task returning the command reply.</returns>
    Task<MxCommandReply> DispatchAsync(StaCommand command);

    /// <summary>
    /// Captures a heartbeat snapshot of the runtime state.
    /// </summary>
    WorkerRuntimeHeartbeatSnapshot CaptureHeartbeat();

    /// <summary>
    /// Drains up to the specified number of pending events from the queue.
    /// </summary>
    /// <param name="maxEvents">Maximum number of events to drain.</param>
    /// <returns>List of drained events.</returns>
    IReadOnlyList<WorkerEvent> DrainEvents(uint maxEvents);

    /// <summary>
    /// Drains a pending fault from the queue, if any.
    /// </summary>
    WorkerFault? DrainFault();

    /// <summary>
    /// Cancels a pending command by correlation ID.
    /// </summary>
    /// <param name="correlationId">Correlation ID of the command to cancel.</param>
    /// <returns>True if the command was found and cancelled; otherwise, false.</returns>
    bool CancelCommand(string correlationId);

    /// <summary>
    /// Requests a graceful shutdown of the session.
    /// </summary>
    void RequestShutdown();

    /// <summary>
    /// Shuts down the session gracefully within the specified timeout.
    /// </summary>
    /// <param name="timeout">Maximum time to allow for graceful shutdown.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    /// <returns>Asynchronous task returning the shutdown result.</returns>
    Task<MxAccessShutdownResult> ShutdownGracefullyAsync(
        TimeSpan timeout,
        CancellationToken cancellationToken = default);
}
