using ZB.MOM.WW.ScadaBridge.Commons.Entities.Audit;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;

namespace ZB.MOM.WW.ScadaBridge.AuditLog.Configuration;

/// <summary>
/// Configuration for Audit Log. Bound from the <c>AuditLog</c> section of
/// <c>appsettings.json</c>. Defaults reflect the design (alog.md §6, §10): an
/// 8 KiB payload-summary cap, a 64 KiB cap on error rows, and a 365-day central
/// retention window with monthly partition-switch purge. The default
/// header-redact list covers HTTP auth headers; per-target overrides extend
/// (never replace) the global redactor set.
/// </summary>
public sealed class AuditLogOptions
{
    /// <summary>Default payload-summary cap in bytes (default 8 KiB).</summary>
    public int DefaultCapBytes { get; set; } = 8192;

    /// <summary>Payload-summary cap on error rows in bytes (default 64 KiB).</summary>
    public int ErrorCapBytes { get; set; } = 65536;

    /// <summary>HTTP headers redacted by default before persistence.</summary>
    public List<string> HeaderRedactList { get; set; } = new()
    {
        "Authorization",
        "X-Api-Key",
        "Cookie",
        "Set-Cookie",
    };

    /// <summary>Body-content redactors applied globally (regex patterns).</summary>
    public List<string> GlobalBodyRedactors { get; set; } = new();

    /// <summary>Per-target redaction overrides keyed by target identifier.</summary>
    public Dictionary<string, PerTargetRedactionOverride> PerTargetOverrides { get; set; } = new();

    /// <summary>Central retention window in days (default 365, range [30, 3650]).</summary>
    public int RetentionDays { get; set; } = 365;

    /// <summary>
    /// Per-channel retention overrides, keyed by the canonical channel name
    /// (the <see cref="AuditChannel"/> enum name — e.g. <c>ApiOutbound</c>,
    /// <c>DbOutbound</c>, <c>Notification</c>, <c>ApiInbound</c>). The value is a
    /// retention window in days that MUST be SHORTER than or equal to the global
    /// <see cref="RetentionDays"/>.
    /// </summary>
    /// <remarks>
    /// <para>
    /// The global <see cref="RetentionDays"/> window is enforced by month-partition
    /// switch-out, which is channel-blind: it can only drop a whole month once every
    /// row in it is older than the global window. A per-channel override therefore
    /// can only ever expire rows EARLIER than the global purge would — never later
    /// (a longer per-channel window is meaningless because the partition switch-out
    /// would already have dropped the month). Overrides shorter than the global window
    /// are honoured by the purge actor as a bounded, batched row DELETE on the
    /// maintenance path (see <c>AuditLogPurgeActor</c>); the append-only writer/ingest
    /// role is unaffected.
    /// </para>
    /// <para>
    /// Each value is validated to be in <c>[30, RetentionDays]</c> by
    /// <c>AuditLogOptionsValidator</c>; keys that are not recognized
    /// <see cref="AuditChannel"/> names are rejected.
    /// </para>
    /// </remarks>
    public Dictionary<string, int> PerChannelRetentionDays { get; set; } = new();

    /// <summary>
    /// Per-body byte ceiling applied to <see cref="AuditEvent.RequestSummary"/> and
    /// <see cref="AuditEvent.ResponseSummary"/> for <see cref="AuditChannel.ApiInbound"/> rows
    /// (default 1 MiB). The 8 KiB / 64 KiB default/error caps that apply to other channels
    /// do not apply here — inbound traffic captures verbatim up to this ceiling and only
    /// then sets <see cref="AuditEvent.PayloadTruncated"/>. See
    /// <c>docs/plans/2026-05-23-inbound-api-full-response-audit-design.md</c>.
    /// </summary>
    public int InboundMaxBytes { get; set; } = 1_048_576;
}
