/* eslint-disable no-console */

export type TokenBucket = {
    take: (n?: number) => Promise<void>;
};

export function createTokenBucket(rps: number, burstMultiplier = 2): TokenBucket {
    const capacity = Math.max(1, Math.floor(rps * burstMultiplier));
    let tokens = capacity;
    const refillPerMs = rps / 1000; // tokens/ms
    let last = Date.now();

    function refill() {
        const now = Date.now();
        const elapsed = now - last;
        if (elapsed > 0) {
            tokens = Math.min(capacity, tokens + elapsed * refillPerMs);
            last = now;
        }
    }

    async function take(n = 1): Promise<void> {
        refill();
        if (tokens >= n) {
            tokens -= n;
            return;
        }
        const deficit = n - tokens;
        const ms = Math.max(1, Math.ceil(deficit / refillPerMs));
        await new Promise((r) => setTimeout(r, ms));
        refill();
        tokens = Math.max(0, tokens - n);
    }

    return { take };
}