import Limiter from "ratelimiter";
import Logger from "../../services/logger.js";
import { redisClient } from "../../db/redis.js";
import { convertMilliseconds } from "../../misc/convert-milliseconds.js";
const logger = new Logger("limiter");
export const limiter = (limitation, actor)=>new Promise((ok, reject)=>{
        if (process.env.NODE_ENV === "test") ok();
        const hasShortTermLimit = typeof limitation.minInterval === "number";
        const hasLongTermLimit = typeof limitation.duration === "number" && typeof limitation.max === "number";
        if (hasShortTermLimit) {
            min();
        } else if (hasLongTermLimit) {
            max();
        } else {
            ok();
        }
        // Short-term limit
        function min() {
            const minIntervalLimiter = new Limiter({
                id: `${actor}:${limitation.key}:min`,
                duration: limitation.minInterval,
                max: 1,
                db: redisClient
            });
            minIntervalLimiter.get((err, info)=>{
                if (err) {
                    return reject("ERR");
                }
                logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);
                if (info.remaining === 0) {
                    reject("BRIEF_REQUEST_INTERVAL");
                } else {
                    if (hasLongTermLimit) {
                        max();
                    } else {
                        ok();
                    }
                }
            });
        }
        // Long term limit
        function max() {
            const limiter = new Limiter({
                id: `${actor}:${limitation.key}`,
                duration: limitation.duration,
                max: limitation.max,
                db: redisClient
            });
            limiter.get((err, info)=>{
                if (err) {
                    return reject("ERR");
                }
                logger.debug(`${actor} ${limitation.key} max remaining: ${info.remaining}`);
                if (info.remaining === 0) {
                    reject({
                        message: "RATE_LIMIT_EXCEEDED",
                        remainingTime: convertMilliseconds(info.resetMs - Date.now())
                    });
                } else {
                    ok();
                }
            });
        }
    });
