namespace ZB.MOM.WW.Telemetry.Serilog;

/// <summary>
/// Seam for project-specific log-event redaction. The shared library applies this via
/// <see cref="RedactionEnricher"/>; each project provides its own implementation that knows which
/// fields (by property name) or which command payloads must not leave the process in log events.
/// If no <see cref="ILogRedactor"/> is registered in DI, <see cref="RedactionEnricher"/> is a no-op.
/// </summary>
public interface ILogRedactor
{
    /// <summary>
    /// Inspects and mutates the supplied log-event <paramref name="properties"/> in place — remove
    /// or replace any sensitive values. Called on every log event before it reaches any sink.
    /// Both removing a key (the property is dropped from the event) and replacing its value are
    /// honoured by <see cref="RedactionEnricher"/>.
    /// <para>
    /// <b>Reach — top-level and nested.</b> A scalar property (e.g. <c>{apiKey}</c>) appears as its
    /// unwrapped CLR value, which you can read and replace directly. A <b>destructured</b> property is
    /// projected into a mutable view you can descend into: a <c>{@Object}</c> arrives as an
    /// <c>IDictionary&lt;string, object?&gt;</c> of its fields, a logged collection as an
    /// <c>IList&lt;object?&gt;</c>, and a logged dictionary as an <c>IDictionary&lt;string, object?&gt;</c>
    /// keyed by the string form of each key — all recursively. You can therefore mask or remove a field
    /// nested inside a destructured object, for example:
    /// <code>if (properties["command"] is IDictionary&lt;string, object?&gt; command) command["apiKey"] = "***";</code>
    /// The structure's type tag and a dictionary's original keys are preserved when the event is
    /// rebuilt, and properties you do not touch are left intact.
    /// </para>
    /// </summary>
    /// <param name="properties">The mutable property dictionary for the current log event.</param>
    void Redact(IDictionary<string, object?> properties);
}
