"""限流器 — 滑动窗口内存计数器。

App1 按 user_id 限流（每用户每分钟 10 次），
App2~8 按 site_id 限流（每门店每小时 100 次）。
内存实现，单实例部署，不依赖外部存储。
"""

from __future__ import annotations

import time
from collections import deque


class RateLimiter:
    """滑动窗口内存限流器。

    - check_user_rate()：App1 每用户每分钟限流
    - check_store_rate()：App2~8 每门店每小时限流

    每个 key 维护一个时间戳 deque，检查时先清除过期条目，
    再判断窗口内请求数是否低于阈值。
    """

    def __init__(self) -> None:
        self._user_windows: dict[str, deque[float]] = {}   # App1: user_id → 时间戳队列
        self._store_windows: dict[str, deque[float]] = {}   # App2~8: site_id → 时间戳队列

    def _check(
        self,
        windows: dict[str, deque[float]],
        key: str,
        limit: int,
        window_seconds: int,
    ) -> bool:
        """通用滑动窗口检查。返回 True 表示允许。"""
        now = time.monotonic()

        if key not in windows:
            windows[key] = deque()

        window = windows[key]

        # 清除窗口外的过期时间戳
        cutoff = now - window_seconds
        while window and window[0] <= cutoff:
            window.popleft()

        # 判断是否超限
        if len(window) >= limit:
            return False

        # 未超限，记录本次请求时间戳
        window.append(now)
        return True

    def check_user_rate(
        self,
        user_id: str,
        limit: int = 10,
        window_seconds: int = 60,
    ) -> bool:
        """App1 每用户每分钟限流。返回 True 表示允许。"""
        return self._check(self._user_windows, user_id, limit, window_seconds)

    def check_store_rate(
        self,
        site_id: int,
        limit: int = 100,
        window_seconds: int = 3600,
    ) -> bool:
        """App2~8 每门店每小时限流。返回 True 表示允许。"""
        # site_id 为 int，转为 str 作为 dict key
        return self._check(self._store_windows, str(site_id), limit, window_seconds)
