"""A small in-process rate limit for the signed-out endpoints (public form
submissions and verification codes): at most `limit` hits per key in a
sliding `window` of seconds. Per API process — enough to blunt a script
hammering one form from one address; a deployment behind several API
processes can add a limit at its proxy as well."""

import time
from collections import deque
from threading import Lock

from fastapi import HTTPException, Request

_hits: dict[str, deque[float]] = {}
_lock = Lock()
_MAX_KEYS = 50_000


def client_ip(request: Request) -> str:
    forwarded = request.headers.get("x-forwarded-for")
    if forwarded:
        return forwarded.split(",")[0].strip()
    return request.client.host if request.client else "unknown"


def check(key: str, limit: int, window: float, message: str = "Too many requests — wait a minute and try again.") -> None:
    """HTTPException 429 once `key` has been hit `limit` times in `window` seconds."""
    now = time.monotonic()
    with _lock:
        if len(_hits) > _MAX_KEYS:
            _hits.clear()
        hits = _hits.setdefault(key, deque())
        while hits and now - hits[0] > window:
            hits.popleft()
        if len(hits) >= limit:
            raise HTTPException(status_code=429, detail=message)
        hits.append(now)


def reset() -> None:
    """Forget every hit — for tests."""
    with _lock:
        _hits.clear()
