"""Persistent per-user rate limiting (shared across processes via the DB)."""

from __future__ import annotations

from datetime import timedelta

from app.database.base import utcnow
from app.database.repositories import Repositories
from app.errors import BlockedUserError, RateLimitedError


class RateLimitService:
    def __init__(self, repos: Repositories) -> None:
        self.repos = repos

    async def enforce(
        self,
        telegram_id: int,
        action: str,
        *,
        max_requests: int,
        window_seconds: int,
        min_interval_seconds: int = 0,
    ) -> None:
        user = await self.repos.users.get_by_telegram_id(telegram_id)
        if user is not None and user.is_blocked:
            raise BlockedUserError("دسترسی شما به این ربات مسدود شده است.")
        now = utcnow()
        window_start = now - timedelta(seconds=window_seconds)
        count = await self.repos.rate_limits.count_since(telegram_id, action, window_start)
        if count >= max_requests:
            raise RateLimitedError(
                window_seconds,
                "تعداد درخواست‌های شما در بازه مجاز بیش از حد است. کمی بعد دوباره تلاش کنید.",
            )
        if min_interval_seconds > 0:
            last = await self.repos.rate_limits.last_event_at(telegram_id, action)
            if last is not None:
                elapsed = (now - last).total_seconds()
                if elapsed < min_interval_seconds:
                    raise RateLimitedError(
                        int(min_interval_seconds - elapsed) + 1,
                        "درخواست‌های متوالی سریع مجاز نیست. چند لحظه صبر کنید.",
                    )
        await self.repos.rate_limits.add(telegram_id, action)
        await self.repos.users.record_request(telegram_id)

    async def prune(self, days: int = 7) -> int:
        return await self.repos.rate_limits.prune(timedelta(days=days))
