namespace Mbproxy;

/// <summary>
/// Service-wide counters for the mbproxy host. Tracks reload accept/reject counts and
/// timestamps so the status page can surface them without coupling to the reconciler.
///
/// <para>Constructed once at DI startup and shared as a singleton. All writes are via
/// dedicated methods that use <see cref="Interlocked"/> so reads from the status page
/// are always coherent without locking.</para>
/// </summary>
public sealed class ServiceCounters
{
    // LastReloadUtc: stored as ticks-since-epoch via Interlocked.Exchange.
    // 0 = "never reloaded". DateTimeOffset.MinValue.UtcTicks works as the sentinel
    // but 0 is simpler. DateTimeOffset.UtcNow.UtcTicks is always > 0 after 1970.
    private long _lastReloadUtcTicks;   // 0 = never; Interlocked
    private int _reloadAppliedCount;    // Interlocked
    private int _reloadRejectedCount;   // Interlocked

    /// <summary>Instant at which this service instance was constructed (service start proxy).</summary>
    public DateTimeOffset StartedAtUtc { get; } = DateTimeOffset.UtcNow;

    /// <summary>
    /// UTC timestamp of the last successfully applied hot-reload, or <c>null</c> if no
    /// reload has been accepted since the service started.
    /// </summary>
    public DateTimeOffset? LastReloadUtc
    {
        get
        {
            long ticks = Interlocked.Read(ref _lastReloadUtcTicks);
            return ticks == 0 ? null : new DateTimeOffset(ticks, TimeSpan.Zero);
        }
    }

    /// <summary>Total number of configuration reloads accepted since service start.</summary>
    public int ReloadAppliedCount
        => Interlocked.CompareExchange(ref _reloadAppliedCount, 0, 0);

    /// <summary>Total number of configuration reloads rejected since service start.</summary>
    public int ReloadRejectedCount
        => Interlocked.CompareExchange(ref _reloadRejectedCount, 0, 0);

    /// <summary>
    /// Records one accepted reload. Bumps <see cref="ReloadAppliedCount"/> and updates
    /// <see cref="LastReloadUtc"/>.
    /// </summary>
    public void RecordReloadApplied(DateTimeOffset timestamp)
    {
        Interlocked.Increment(ref _reloadAppliedCount);
        Interlocked.Exchange(ref _lastReloadUtcTicks, timestamp.UtcTicks);
    }

    /// <summary>Bumps <see cref="ReloadRejectedCount"/>.</summary>
    public void RecordReloadRejected()
        => Interlocked.Increment(ref _reloadRejectedCount);
}
