using System.Collections.Generic;
using ZB.MOM.WW.OtOpcUa.Core.AlarmHistorian;

namespace ZB.MOM.WW.OtOpcUa.Runtime.Historian;

/// <summary>
///     Binds the <c>AlarmHistorian</c> configuration section that gates the durable
///     store-and-forward alarm sink. When <see cref="Enabled"/> is <c>true</c>,
///     <c>AddAlarmHistorian</c> registers a <c>LocalDbStoreAndForwardSink</c> (draining to the
///     gateway alarm writer supplied by the Host) in place of the
///     <c>NullAlarmHistorianSink</c> default; otherwise the Null default survives. This section
///     supplies only the <see cref="Enabled"/> gate and the store-and-forward knobs — the
///     downstream connection (endpoint/key/TLS) is sourced from the <c>ServerHistorian</c> section,
///     and the queue's storage location is the node's consolidated <c>LocalDb:Path</c> database.
/// </summary>
public sealed class AlarmHistorianOptions
{
    /// <summary>The configuration section name this options class binds.</summary>
    public const string SectionName = "AlarmHistorian";

    /// <summary>
    ///     When <c>true</c>, the durable SQLite store-and-forward sink is registered; when
    ///     <c>false</c> (the default) the no-op <c>NullAlarmHistorianSink</c> stays in place.
    /// </summary>
    public bool Enabled { get; init; }

    /// <summary>Maximum number of queued rows the drain worker forwards in a single batch.</summary>
    public int BatchSize { get; init; } = 100;

    /// <summary>Seconds between drain-worker ticks. Defaults to 5.</summary>
    public int DrainIntervalSeconds { get; init; } = 5;

    /// <summary>Maximum queued rows before the sink evicts the oldest. Defaults to 1,000,000
    /// (matches <c>LocalDbStoreAndForwardSink</c>'s <c>DefaultCapacity</c>).</summary>
    public long Capacity { get; init; } = LocalDbStoreAndForwardSink.DefaultCapacity;

    /// <summary>Days to retain dead-lettered rows before purge. Defaults to 30.</summary>
    public int DeadLetterRetentionDays { get; init; } = 30;

    /// <summary>Maximum delivery attempts before a perpetually-retrying (poison) row is dead-lettered.
    /// Defaults to 10 (matches <c>LocalDbStoreAndForwardSink</c>'s <c>DefaultMaxAttempts</c>).</summary>
    public int MaxAttempts { get; init; } = LocalDbStoreAndForwardSink.DefaultMaxAttempts;

    /// <summary>Returns operator-facing misconfiguration warnings for an <c>Enabled</c> historian
    /// (empty when disabled or correctly configured). Pure — the registration logs each entry.</summary>
    /// <returns>Zero or more human-readable warning messages.</returns>
    public IReadOnlyList<string> Validate()
    {
        var warnings = new List<string>();
        if (!Enabled) return warnings;
        if (DrainIntervalSeconds <= 0)
            warnings.Add($"AlarmHistorian:DrainIntervalSeconds is {DrainIntervalSeconds} — must be > 0; the drain timer will throw or spin at startup.");
        if (Capacity <= 0)
            warnings.Add($"AlarmHistorian:Capacity is {Capacity} — must be > 0; the sink constructor will throw at startup.");
        if (DeadLetterRetentionDays <= 0)
            warnings.Add($"AlarmHistorian:DeadLetterRetentionDays is {DeadLetterRetentionDays} — must be > 0; dead-lettered rows would be purged on every drain tick.");
        if (MaxAttempts <= 0)
            warnings.Add($"AlarmHistorian:MaxAttempts is {MaxAttempts} — must be > 0; the sink constructor will throw at startup.");
        return warnings;
    }
}
