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

/// <summary>
///     Configuration for the gateway's always-on central alarm monitor
///     (<see cref="Alarms.GatewayAlarmMonitor"/>). When <see cref="Enabled"/>
///     is true the gateway opens one gateway-owned worker session dedicated to
///     alarms, caches the active-alarm set, and fans it out to every client
///     through the <c>StreamAlarms</c> RPC — no client opens its own session
///     to see alarms.
/// </summary>
/// <remarks>
///     Defaults preserve current behaviour (alarm monitoring disabled).
///     Operators opt in by setting <c>MxGateway:Alarms:Enabled = true</c> and
///     supplying a canonical <c>\\&lt;machine&gt;\Galaxy!&lt;area&gt;</c>
///     subscription expression. The literal "Galaxy" provider is correct
///     regardless of the configured Galaxy database name (the wnwrap consumer
///     does not accept the database name as the provider).
/// </remarks>
public sealed class AlarmsOptions
{
    /// <summary>Gate the gateway's always-on central alarm monitor. Default false.</summary>
    public bool Enabled { get; init; }

    /// <summary>
    ///     AVEVA alarm-subscription expression the monitor subscribes on
    ///     startup. When empty and <see cref="Enabled"/> is true, the gateway
    ///     falls back to <c>\\$(MachineName)\Galaxy!$(DefaultArea)</c> if
    ///     <see cref="DefaultArea"/> is set; otherwise the monitor faults with
    ///     a configuration diagnostic.
    /// </summary>
    public string SubscriptionExpression { get; init; } = string.Empty;

    /// <summary>
    ///     Optional area name used to compose a default subscription when
    ///     <see cref="SubscriptionExpression"/> is empty. Combined with
    ///     <c>Environment.MachineName</c> as
    ///     <c>\\&lt;MachineName&gt;\Galaxy!&lt;DefaultArea&gt;</c>.
    /// </summary>
    public string DefaultArea { get; init; } = string.Empty;

    /// <summary>
    ///     How often the monitor reconciles its in-process alarm cache against
    ///     the worker's authoritative active-alarm snapshot, catching any
    ///     transitions the live poll-and-diff feed missed. Default 30 seconds;
    ///     the monitor floors it at 5 seconds.
    /// </summary>
    public int ReconcileIntervalSeconds { get; init; } = 30;

    /// <summary>
    ///     Cadence at which the worker's STA polls the AVEVA alarm consumer
    ///     (<c>GetXmlCurrentAlarms2</c>) for the current active-alarm snapshot.
    ///     Default 500 ms; must be between 100 ms and 3,600,000 ms (one hour).
    ///     Every poll is a COM call plus an XML parse on the STA that also
    ///     serves reads and writes, so driving it below 100 ms starves the
    ///     command path; above an hour the cadence stops being a cadence and
    ///     silently disables alarm polling. Conveyed to the worker through the
    ///     <c>MXGATEWAY_ALARM_POLL_INTERVAL_MS</c> environment variable.
    /// </summary>
    public int PollIntervalMilliseconds { get; init; } = 500;

    /// <summary>
    ///     Cap the worker passes to <c>GetXmlCurrentAlarms2</c>'s
    ///     <c>maxAlmCnt</c> argument. Default 1024; must be between 64 and
    ///     65,536 — the worker is a 32-bit process that materializes each
    ///     fetch as one BSTR plus a full XmlDocument, so an unbounded cap
    ///     faults the STA rather than merely slowing it. A fetch that comes
    ///     back holding exactly this many records is treated as truncated: the
    ///     worker keeps the alarms the capped fetch could not mention in its
    ///     snapshot rather than letting their absence read as a clear. Raise it
    ///     on galaxies whose steady-state active-alarm count approaches the
    ///     cap. Conveyed to the worker through the
    ///     <c>MXGATEWAY_ALARM_MAX_ALARMS_PER_FETCH</c> environment variable.
    /// </summary>
    public int MaxAlarmsPerFetch { get; init; } = 1024;

    /// <summary>
    ///     Configuration for the alarm-manager ↔ subtag fallback mechanism:
    ///     operating mode, failure-detection thresholds, discovery, and subtag
    ///     names. Defaults (Mode = "Auto") preserve behaviour when the section is
    ///     omitted from configuration.
    /// </summary>
    public AlarmFallbackOptions Fallback { get; init; } = new();
}
