# backend/app/connectors/ratelimit.py — 토큰 버킷 + 429/Retry-After 지수 백오프 (phase-13)
import threading
import time

import httpx


class RateLimiter:
    """간단 토큰 버킷 + 429/Retry-After 지수 백오프."""

    def __init__(self, rate: float = 4, per: float = 1.0, max_backoff: float = 32.0):
        self.rate, self.per = rate, per
        self.allowance = rate
        self.last = time.monotonic()
        self.max_backoff = max_backoff
        self._lock = threading.Lock()

    def acquire(self) -> None:
        with self._lock:
            now = time.monotonic()
            self.allowance += (now - self.last) * (self.rate / self.per)
            self.last = now
            if self.allowance > self.rate:
                self.allowance = self.rate
            if self.allowance < 1.0:
                time.sleep((1.0 - self.allowance) * (self.per / self.rate))
                self.allowance = 0.0
            else:
                self.allowance -= 1.0

    def handle_response(self, r: "httpx.Response", attempt: int = 0) -> bool:
        """429 면 Retry-After(또는 지수 백오프)만큼 대기 후 True(재시도) 반환."""
        if r.status_code == 429:
            retry = float(r.headers.get("Retry-After", min(2**attempt, self.max_backoff)))
            time.sleep(min(retry, self.max_backoff))
            return True
        return False
