using ZB.MOM.WW.Configuration;

namespace ZB.MOM.WW.ScadaBridge.SiteEventLogging;

/// <summary>
/// Validates <see cref="SiteEventLogOptions"/> at startup. Retention/purge values
/// drive the daily purge PeriodicTimer (a zero/negative period trips
/// <see cref="ArgumentOutOfRangeException"/>), the paging bounds gate query result
/// sizes, and the write-queue capacity sizes a bounded channel; a
/// <c>MaxQueryPageSize</c> below <c>QueryPageSize</c> would silently clamp the
/// default page below itself. Registered with <c>ValidateOnStart()</c> so a bad
/// <c>ScadaBridge:SiteEventLog</c> section fails fast at boot with a clear,
/// key-naming message.
/// </summary>
public sealed class SiteEventLogOptionsValidator : OptionsValidatorBase<SiteEventLogOptions>
{
    /// <inheritdoc />
    protected override void Validate(ValidationBuilder builder, SiteEventLogOptions options)
    {
        builder.RequireThat(options.RetentionDays > 0,
            $"ScadaBridge:SiteEventLog:RetentionDays must be greater than 0 " +
            $"(was {options.RetentionDays}).");

        builder.RequireThat(options.MaxStorageMb > 0,
            $"ScadaBridge:SiteEventLog:MaxStorageMb must be greater than 0 " +
            $"(was {options.MaxStorageMb}).");

        builder.RequireThat(!string.IsNullOrWhiteSpace(options.DatabasePath),
            "ScadaBridge:SiteEventLog:DatabasePath must be a non-empty path; " +
            "it is the SQLite file backing the site event log.");

        builder.RequireThat(options.QueryPageSize > 0,
            $"ScadaBridge:SiteEventLog:QueryPageSize must be greater than 0 " +
            $"(was {options.QueryPageSize}).");

        builder.RequireThat(options.WriteQueueCapacity > 0,
            $"ScadaBridge:SiteEventLog:WriteQueueCapacity must be greater than 0 " +
            $"(was {options.WriteQueueCapacity}); it bounds the background write channel.");

        builder.RequireThat(options.PurgeInterval > TimeSpan.Zero,
            $"ScadaBridge:SiteEventLog:PurgeInterval must be a positive duration " +
            $"(was {options.PurgeInterval}); it is the purge PeriodicTimer period.");

        // The hard page-size ceiling clamps a caller-supplied PageSize; a ceiling
        // below the default QueryPageSize would silently clamp the default below
        // itself. Only meaningful when both are positive (owned above), so stay
        // silent when either is non-positive rather than double-firing.
        builder.RequireThat(
            !(options.QueryPageSize > 0
              && options.MaxQueryPageSize > 0
              && options.MaxQueryPageSize < options.QueryPageSize),
            $"ScadaBridge:SiteEventLog:MaxQueryPageSize ({options.MaxQueryPageSize}) " +
            $"must be >= QueryPageSize ({options.QueryPageSize}): the ceiling clamps a caller's " +
            "requested page size, so it cannot be smaller than the default page size.");
    }
}
