namespace ZB.MOM.WW.OtOpcUa.Security.Audit;

/// <summary>
/// Default-resolution helpers for the <c>Actor</c> field of a canonical
/// <c>ZB.MOM.WW.Audit.AuditEvent</c>.
/// </summary>
/// <remarks>
/// <para>
/// Usage pattern — call <see cref="Resolve"/> when constructing an <c>AuditEvent</c>:
/// <code>
/// new AuditEvent
/// {
///     Actor  = AuditActor.Resolve(auditActorAccessor),
///     ...
/// }
/// </code>
/// </para>
/// <para>
/// <b>Note:</b> OtOpcUa has no live structured <c>AuditEvent</c> emit sites as of Phase 3
/// (all production audit flows through the bespoke stored-procedure path). This helper is
/// forward-looking — it is tested and ready so that future emit sites pick up the correct
/// Actor automatically.
/// </para>
/// </remarks>
public static class AuditActor
{
    /// <summary>The fallback actor string used when no authenticated principal is available.</summary>
    public const string SystemFallback = "system";

    /// <summary>
    /// Returns the current principal's actor string from <paramref name="accessor"/>, or
    /// <see cref="SystemFallback"/> when the accessor returns <see langword="null"/>
    /// (no HTTP context, unauthenticated, or in a background/non-HTTP execution context).
    /// </summary>
    /// <param name="accessor">The audit-actor accessor. May be <see langword="null"/>
    /// (e.g. in a background context where DI did not wire the accessor).</param>
    /// <returns>The actor string — never <see langword="null"/>.</returns>
    public static string Resolve(IAuditActorAccessor? accessor) =>
        Resolve(accessor, SystemFallback);

    /// <summary>
    /// Returns the current principal's actor string from <paramref name="accessor"/>, or
    /// <paramref name="fallback"/> when the accessor returns <see langword="null"/>.
    /// </summary>
    /// <param name="accessor">The audit-actor accessor. May be <see langword="null"/>.</param>
    /// <param name="fallback">The explicit fallback value.</param>
    /// <returns>The actor string — never <see langword="null"/>.</returns>
    public static string Resolve(IAuditActorAccessor? accessor, string fallback) =>
        accessor?.CurrentActor ?? fallback;
}
