using Microsoft.Extensions.Options;

namespace ZB.MOM.WW.ScadaBridge.NotificationOutbox;

/// <summary>
/// Configuration options for the SMS (Twilio-REST) notification delivery adapter,
/// bound from the <c>ScadaBridge:Sms</c> configuration section.
///
/// SMS connection settings are primarily carried by the deployed
/// <c>SmsConfiguration</c> entity. These values supply the documented fallbacks /
/// caps used by the central Notification Outbox's
/// <c>SmsNotificationDeliveryAdapter</c>: <see cref="MaxMessageLength"/> caps the
/// composed body, and <see cref="ConnectionTimeoutSeconds"/> is the per-request
/// timeout used when the deployed <c>SmsConfiguration.ConnectionTimeoutSeconds</c>
/// field is left unset (non-positive) — a value present on the row always takes
/// precedence.
/// </summary>
public sealed class SmsOptions
{
    /// <summary>
    /// Maximum length of the composed SMS body; longer bodies are truncated with an
    /// ellipsis before the Twilio POST. Default 1600 (Twilio's per-message maximum).
    /// Must be strictly positive.
    /// </summary>
    public int MaxMessageLength { get; set; } = 1600;

    /// <summary>
    /// Per-request connection/response timeout (seconds) used when the deployed
    /// <c>SmsConfiguration.ConnectionTimeoutSeconds</c> is unset (non-positive).
    /// Default 30s. Must be strictly positive.
    /// </summary>
    public int ConnectionTimeoutSeconds { get; set; } = 30;
}

/// <summary>
/// Validates <see cref="SmsOptions"/> on startup. A non-positive
/// <see cref="SmsOptions.MaxMessageLength"/> would truncate every body to nothing,
/// and a non-positive <see cref="SmsOptions.ConnectionTimeoutSeconds"/> would make
/// the per-request timeout meaningless, so both are required to be strictly positive.
/// </summary>
public sealed class SmsOptionsValidator : IValidateOptions<SmsOptions>
{
    /// <summary>
    /// Validates that a bound <see cref="SmsOptions"/> instance is usable, failing
    /// fast at startup if any value is not strictly positive.
    /// </summary>
    /// <param name="name">The named options instance being validated, or <c>null</c> for the default instance.</param>
    /// <param name="options">The bound <see cref="SmsOptions"/> instance to validate.</param>
    /// <returns>A successful result, or a failure result listing every invalid field.</returns>
    public ValidateOptionsResult Validate(string? name, SmsOptions options)
    {
        ArgumentNullException.ThrowIfNull(options);

        var failures = new List<string>();

        if (options.MaxMessageLength <= 0)
        {
            failures.Add(
                $"ScadaBridge:Sms:{nameof(SmsOptions.MaxMessageLength)} ({options.MaxMessageLength}) " +
                "must be > 0; it caps the composed SMS body length.");
        }

        if (options.ConnectionTimeoutSeconds <= 0)
        {
            failures.Add(
                $"ScadaBridge:Sms:{nameof(SmsOptions.ConnectionTimeoutSeconds)} ({options.ConnectionTimeoutSeconds}) " +
                "must be > 0; it is the per-request Twilio timeout fallback.");
        }

        return failures.Count > 0
            ? ValidateOptionsResult.Fail(failures)
            : ValidateOptionsResult.Success;
    }
}
