using ZB.MOM.WW.Telemetry.Serilog;

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

/// <summary>
/// Adapts the static <see cref="GatewayLogRedactor"/> to the shared <see cref="ILogRedactor"/> seam
/// so the telemetry RedactionEnricher masks API-key/credential material on every log event.
/// </summary>
public sealed class GatewayLogRedactorSeam : ILogRedactor
{
    private static readonly string[] IdentityKeys = ["ClientIdentity", "authorization", "Authorization"];

    /// <summary>Property name carrying the MXAccess command method, which gates value redaction.</summary>
    private const string CommandMethodProperty = "CommandMethod";

    /// <summary>Property name carrying a command payload value that may bear credentials.</summary>
    private const string CommandValueProperty = "CommandValue";

    /// <summary>
    /// Masks API-key/credential material in known identity-bearing log properties, and any
    /// command payload value.
    /// </summary>
    /// <param name="properties">The log event property dictionary to redact in place.</param>
    public void Redact(IDictionary<string, object?> properties)
    {
        ArgumentNullException.ThrowIfNull(properties);
        foreach (var key in IdentityKeys)
        {
            if (properties.TryGetValue(key, out var value) && value is string s)
            {
                properties[key] = GatewayLogRedactor.RedactClientIdentity(s);
            }
        }

        RedactCommandValue(properties);
    }

    /// <summary>
    /// Masks a command payload value. Value logging is off here — the seam exposes no opt-in — so
    /// every non-null value is masked, credential-bearing command or not.
    /// </summary>
    /// <param name="properties">The log event property dictionary to redact in place.</param>
    private static void RedactCommandValue(IDictionary<string, object?> properties)
    {
        if (!properties.TryGetValue(CommandValueProperty, out object? value) || value is null)
        {
            return;
        }

        string? commandMethod = properties.TryGetValue(CommandMethodProperty, out object? method)
            ? method as string
            : null;

        properties[CommandValueProperty] = GatewayLogRedactor.RedactCommandValue(commandMethod, value);
    }
}
