package com.ttstd.signaling.security;

import org.springframework.stereotype.Component;

import java.time.Instant;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 简易固定窗口限流器，用于登录、激活、握手等敏感入口的防爆破。
 *
 * <p>当前为单机内存实现；多实例部署时应替换为 Redis 计数。
 */
@Component
public class RateLimiter {

    private static final class Window {
        final AtomicInteger count = new AtomicInteger();
        volatile Instant resetAt;

        Window(Instant resetAt) {
            this.resetAt = resetAt;
        }
    }

    private final Map<String, Window> windows = new ConcurrentHashMap<>();

    /**
     * 尝试消费一次配额。
     *
     * @param key           限流键（如 "login:" + ip）
     * @param maxRequests   窗口内最大次数
     * @param windowSeconds 窗口长度（秒）
     * @return true 表示允许，false 表示已超限
     */
    public boolean tryAcquire(String key, int maxRequests, long windowSeconds) {
        Instant now = Instant.now();
        Window window = windows.compute(key, (k, existing) -> {
            if (existing == null || now.isAfter(existing.resetAt)) {
                return new Window(now.plusSeconds(windowSeconds));
            }
            return existing;
        });
        return window.count.incrementAndGet() <= maxRequests;
    }

    /** 重置指定键的计数（例如登录成功后清空失败计数）。 */
    public void reset(String key) {
        windows.remove(key);
    }

    /** 清理已过期窗口，避免内存无限增长。由定时任务调用。 */
    public void evictExpired() {
        Instant now = Instant.now();
        windows.entrySet().removeIf(e -> now.isAfter(e.getValue().resetAt));
    }

    public int size() {
        return windows.size();
    }
}
