using System;
using System.Threading;
using Google.Protobuf.WellKnownTypes;
using ZB.MOM.WW.MxGateway.Contracts.Proto;

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

public sealed class StaCommand
{
    /// <summary>Initializes a new instance of the <see cref="StaCommand"/> class.</summary>
    /// <param name="sessionId">Identifier of the session.</param>
    /// <param name="correlationId">Correlation identifier for the command.</param>
    /// <param name="command">The MXAccess command to execute.</param>
    /// <param name="enqueueTimestamp">Timestamp when the command was enqueued.</param>
    /// <param name="cancellationToken">Token to cancel the asynchronous operation.</param>
    public StaCommand(
        string sessionId,
        string correlationId,
        MxCommand command,
        Timestamp? enqueueTimestamp = null,
        CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrWhiteSpace(sessionId))
        {
            throw new ArgumentException("STA command requires a session id.", nameof(sessionId));
        }

        if (string.IsNullOrWhiteSpace(correlationId))
        {
            throw new ArgumentException("STA command requires a correlation id.", nameof(correlationId));
        }

        SessionId = sessionId;
        CorrelationId = correlationId;
        Command = command ?? throw new ArgumentNullException(nameof(command));
        EnqueueTimestamp = enqueueTimestamp ?? Timestamp.FromDateTime(DateTime.UtcNow);
        CancellationToken = cancellationToken;
    }

    /// <summary>Gets the session ID for the STA command.</summary>
    public string SessionId { get; }

    /// <summary>Gets the correlation ID for the STA command.</summary>
    public string CorrelationId { get; }

    /// <summary>Gets the MXAccess command to execute.</summary>
    public MxCommand Command { get; }

    /// <summary>Gets the timestamp when the command was enqueued.</summary>
    public Timestamp EnqueueTimestamp { get; }

    /// <summary>Gets the token to cancel the asynchronous operation.</summary>
    public CancellationToken CancellationToken { get; }

    /// <summary>Gets the kind of the MXAccess command.</summary>
    public MxCommandKind Kind => Command.Kind;

    /// <summary>Gets the method name of the command.</summary>
    public string MethodName => Kind.ToString();
}
