using ZB.MOM.WW.MxGateway.Server.Security.Authentication;
using ZB.MOM.WW.MxGateway.Server.Sessions;

namespace ZB.MOM.WW.MxGateway.Server.Security.Authorization;

public interface IConstraintEnforcer
{
    /// <summary>Checks whether a read constraint is satisfied for a tag address.</summary>
    /// <param name="identity">The API key identity.</param>
    /// <param name="tagAddress">Tag address to check.</param>
    /// <param name="cancellationToken">Token to observe for cancellation.</param>
    Task<ConstraintFailure?> CheckReadTagAsync(
        ApiKeyIdentity? identity,
        string tagAddress,
        CancellationToken cancellationToken);

    /// <summary>Checks whether a read constraint is satisfied for an item handle.</summary>
    /// <param name="identity">The API key identity.</param>
    /// <param name="session">The gateway session.</param>
    /// <param name="serverHandle">The MXAccess server handle.</param>
    /// <param name="itemHandle">The MXAccess item handle.</param>
    /// <param name="cancellationToken">Token to observe for cancellation.</param>
    Task<ConstraintFailure?> CheckReadHandleAsync(
        ApiKeyIdentity? identity,
        GatewaySession session,
        int serverHandle,
        int itemHandle,
        CancellationToken cancellationToken);

    /// <summary>Checks whether a write constraint is satisfied for an item handle.</summary>
    /// <param name="identity">The API key identity.</param>
    /// <param name="session">The gateway session.</param>
    /// <param name="serverHandle">The MXAccess server handle.</param>
    /// <param name="itemHandle">The MXAccess item handle.</param>
    /// <param name="cancellationToken">Token to observe for cancellation.</param>
    Task<ConstraintFailure?> CheckWriteHandleAsync(
        ApiKeyIdentity? identity,
        GatewaySession session,
        int serverHandle,
        int itemHandle,
        CancellationToken cancellationToken);

    /// <summary>Records a constraint denial for audit and metrics.</summary>
    /// <param name="identity">The API key identity.</param>
    /// <param name="commandKind">The kind of command denied.</param>
    /// <param name="target">The target of the denied command.</param>
    /// <param name="failure">The constraint failure details.</param>
    /// <param name="correlationId">
    ///     The per-request client correlation id, if any. Stored on the audit record's
    ///     <c>CorrelationId</c> when it parses as a GUID; otherwise left null.
    /// </param>
    /// <param name="cancellationToken">Token to observe for cancellation.</param>
    Task RecordDenialAsync(
        ApiKeyIdentity? identity,
        string commandKind,
        string target,
        ConstraintFailure failure,
        string? correlationId,
        CancellationToken cancellationToken);
}
