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

/// <summary>
///     Controls how the central alarm monitor selects between the MXAccess
///     alarm-manager subscription and the subtag-polling fallback, and
///     governs the failure-detection thresholds used when switching.
/// </summary>
public sealed class AlarmFallbackOptions
{
    /// <summary>
    ///     Selects the operating mode for the alarm-manager ↔ subtag fallback
    ///     mechanism. Accepted values (case-insensitive):
    ///     <list type="bullet">
    ///         <item><c>Auto</c> — use the alarm manager; switch to subtag polling
    ///         automatically when <see cref="ConsecutiveFailureThreshold"/> failures
    ///         are detected, and probe for failback.</item>
    ///         <item><c>ForceAlarmManager</c> — always use the alarm manager;
    ///         never fall back.</item>
    ///         <item><c>ForceSubtag</c> — always use subtag polling;
    ///         never try the alarm manager.</item>
    ///     </list>
    ///     Default is <c>Auto</c>.
    /// </summary>
    public string Mode { get; init; } = "Auto";

    /// <summary>
    ///     Number of consecutive alarm-manager failures before the monitor
    ///     switches to subtag-polling fallback. Must be at least 1. Default 3.
    /// </summary>
    public int ConsecutiveFailureThreshold { get; init; } = 3;

    /// <summary>
    ///     How often (in seconds) the monitor sends a probe to the alarm manager
    ///     while operating in subtag-polling fallback mode, to detect recovery.
    ///     Must be at least 1. Default 30.
    /// </summary>
    public int FailbackProbeIntervalSeconds { get; init; } = 30;

    /// <summary>
    ///     Number of consecutive successful probes required before the monitor
    ///     considers the alarm manager recovered and switches back. Must be at
    ///     least 1. Default 3.
    /// </summary>
    public int FailbackStableProbes { get; init; } = 3;

    /// <summary>
    ///     Controls how the monitor discovers the set of objects to poll when
    ///     operating in subtag-polling fallback mode.
    /// </summary>
    public AlarmDiscoveryOptions Discovery { get; init; } = new();

    /// <summary>
    ///     Configures the subtag names the monitor reads when polling alarm state
    ///     in subtag-fallback mode.
    /// </summary>
    public AlarmSubtagNameOptions Subtags { get; init; } = new();
}

/// <summary>
///     Governs how the alarm monitor discovers objects to include in subtag-polling
///     fallback mode. Either the Galaxy Repository query (when
///     <see cref="UseGalaxyRepository"/> is <c>true</c>) or an explicit
///     <see cref="IncludeAttributes"/> list must be supplied when
///     <c>MxGateway:Alarms:Fallback:Mode</c> is <c>ForceSubtag</c>.
/// </summary>
public sealed class AlarmDiscoveryOptions
{
    /// <summary>
    ///     When <c>true</c> the monitor queries the Galaxy Repository SQL database
    ///     to enumerate alarm objects for the configured area. Default <c>true</c>.
    /// </summary>
    public bool UseGalaxyRepository { get; init; } = true;

    /// <summary>
    ///     Galaxy area to scope the Repository query to. When empty the monitor
    ///     falls back to <see cref="AlarmsOptions.DefaultArea"/>. Ignored when
    ///     <see cref="UseGalaxyRepository"/> is <c>false</c>.
    /// </summary>
    public string Area { get; init; } = string.Empty;

    /// <summary>
    ///     Explicit list of MXAccess attribute paths to include in subtag polling,
    ///     supplementing (or replacing, when <see cref="UseGalaxyRepository"/> is
    ///     <c>false</c>) the Repository-derived list. Default empty.
    /// </summary>
    public string[] IncludeAttributes { get; init; } = Array.Empty<string>();

    /// <summary>
    ///     Attribute paths to remove from the merged poll list (case-insensitive).
    ///     The exclude runs after the Repository-derived rows and the explicit
    ///     <see cref="IncludeAttributes"/> entries are combined, so an exclude that
    ///     matches an explicit include suppresses it too — excludes win.
    ///     Ignored when <see cref="UseGalaxyRepository"/> is <c>false</c>.
    ///     Default empty.
    /// </summary>
    public string[] ExcludeAttributes { get; init; } = Array.Empty<string>();
}

/// <summary>
///     Configures the subtag names read by the alarm monitor when it is operating
///     in subtag-polling fallback mode. Names are matched against MXAccess item
///     handles; validation against the live MXAccess attribute list occurs at
///     runtime, not at startup.
///     Defaults are the confirmed AVEVA <c>AlarmExtension</c> primitive field names,
///     verified against the live ZB Galaxy <c>attribute_definition</c> rows.
/// </summary>
public sealed class AlarmSubtagNameOptions
{
    /// <summary>
    ///     Subtag name for the in-alarm boolean. Confirmed AVEVA <c>AlarmExtension</c>
    ///     field name. Default <c>InAlarm</c>.
    /// </summary>
    public string Active { get; init; } = "InAlarm";

    /// <summary>
    ///     Subtag name for the acknowledged boolean. Confirmed AVEVA <c>AlarmExtension</c>
    ///     field name. Default <c>Acked</c>.
    /// </summary>
    public string Acked { get; init; } = "Acked";

    /// <summary>
    ///     Subtag name for the acknowledgement comment write target. Writing this subtag
    ///     performs the acknowledge in AVEVA. Confirmed AVEVA <c>AlarmExtension</c>
    ///     field name. When empty the ack-comment write path is disabled.
    ///     Default <c>AckMsg</c>.
    /// </summary>
    public string AckComment { get; init; } = "AckMsg";

    /// <summary>
    ///     Subtag name for the alarm priority / severity. Confirmed AVEVA
    ///     <c>AlarmExtension</c> field name. Default <c>Priority</c>.
    /// </summary>
    public string Priority { get; init; } = "Priority";
}
