// Physically lives under Interfaces/Services/ to match the
// established subfolder convention (REQ-COM-5b), but the namespace stays
// `ZB.MOM.WW.ScadaBridge.Commons.Interfaces` to avoid a cascading update to consumers
// across ZB.MOM.WW.ScadaBridge.AuditLog and ZB.MOM.WW.ScadaBridge.ConfigurationDatabase. Adopting
// the canonical `ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Services` namespace can be
// picked up alongside any future Commons-wide namespace tidy-up.
namespace ZB.MOM.WW.ScadaBridge.Commons.Interfaces;

/// <summary>
/// Abstraction over the central AuditLog partition-function roll-forward
/// operation. A daily-cadence hosted service
/// (<c>AuditLogPartitionMaintenanceService</c>) calls
/// <see cref="EnsureLookaheadAsync"/> to make sure
/// <c>pf_AuditLog_Month</c> always has at least <c>LookaheadMonths</c> of
/// future boundaries available — otherwise inserts past the highest
/// boundary land in a single ever-growing tail partition that
/// <c>SwitchOutPartitionAsync</c> cannot purge cleanly.
/// </summary>
/// <remarks>
/// <para>
/// The interface lives in <c>ZB.MOM.WW.ScadaBridge.Commons</c> so the central hosted
/// service in <c>ZB.MOM.WW.ScadaBridge.AuditLog</c> can depend on it without taking a
/// reference on <c>ZB.MOM.WW.ScadaBridge.ConfigurationDatabase</c>; the EF-based
/// implementation ships in
/// <c>ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Maintenance.AuditLogPartitionMaintenance</c>
/// and is registered by <c>AddConfigurationDatabase</c>.
/// </para>
/// <para>
/// Both methods read <c>sys.partition_range_values</c> / mutate
/// <c>pf_AuditLog_Month</c> via raw SQL — there is no EF model for a
/// partition function. The interface deliberately exposes only the two
/// operations the hosted service needs; it is not a general partition-DDL
/// surface.
/// </para>
/// </remarks>
public interface IPartitionMaintenance
{
    /// <summary>
    /// Splits new monthly boundaries on <c>pf_AuditLog_Month</c> so the
    /// function covers at least <paramref name="lookaheadMonths"/> future
    /// months relative to <see cref="DateTime.UtcNow"/>. Idempotent — a
    /// boundary that already exists is skipped rather than re-issued.
    /// Returns the boundaries actually added, in chronological order.
    /// </summary>
    /// <param name="lookaheadMonths">Number of future monthly boundaries to ensure exist.</param>
    /// <param name="ct">Cancellation token for the SQL operation.</param>
    /// <returns>A task that resolves to the list of boundary values actually added, in chronological order.</returns>
    Task<IReadOnlyList<DateTime>> EnsureLookaheadAsync(int lookaheadMonths, CancellationToken ct = default);

    /// <summary>
    /// Reads the current maximum boundary value from
    /// <c>sys.partition_range_values</c> for <c>pf_AuditLog_Month</c>.
    /// Returns <c>null</c> when the partition function does not exist or
    /// has no boundaries.
    /// </summary>
    /// <param name="ct">Cancellation token for the SQL operation.</param>
    /// <returns>A task that resolves to the highest boundary value, or <c>null</c> when the partition function has no boundaries.</returns>
    Task<DateTime?> GetMaxBoundaryAsync(CancellationToken ct = default);
}
