// Archivo: Elecciones.Infrastructure/Services/RateLimiterService.cs
using System.Threading;
using System.Threading.Tasks;

namespace Elecciones.Infrastructure.Services;

public class RateLimiterService
{
    private readonly SemaphoreSlim _semaphore;
    private readonly int _limit;
    private readonly TimeSpan _period;
    private Timer _timer;

    public RateLimiterService(int limit, TimeSpan period)
    {
        _limit = limit;
        _period = period;
        _semaphore = new SemaphoreSlim(limit, limit);

        // Un temporizador que "rellena el cubo" cada 5 minutos.
        _timer = new Timer(
            callback: _ => RefillBucket(),
            state: null,
            dueTime: period,
            period: period);
    }

    private void RefillBucket()
    {
        // Calcula cuántas fichas faltan en el cubo.
        var releaseCount = _limit - _semaphore.CurrentCount;
        if (releaseCount > 0)
        {
            // Añade las fichas que faltan.
            _semaphore.Release(releaseCount);
        }
    }

    // El método que usarán nuestras tareas para "pedir una ficha".
    public async Task WaitAsync(CancellationToken cancellationToken = default)
    {
        await _semaphore.WaitAsync(cancellationToken);
    }
}