import time
import redis
from app.core.config import get_settings

settings = get_settings()


class RateLimiter:
    """Token bucket rate limiter using Redis"""
    
    def __init__(self):
        self.redis_client = redis.from_url(settings.REDIS_URL, decode_responses=True)
        self.bucket_size = settings.RATE_LIMIT_BUCKET_SIZE
        self.refill_rate = settings.RATE_LIMIT_REFILL_RATE_PER_SEC
    
    def check_and_consume(self, key: str, tokens: int = 1, bucket_size: int | None = None, refill_rate: float | None = None) -> bool:
        """
        Check if request is allowed under rate limit and consume tokens
        
        Args:
            key: rate limit key (e.g., "tenant:123:telegram" or "tenant:123")
            tokens: number of tokens to consume (default: 1)
            bucket_size: override default bucket size (optional)
            refill_rate: override default refill rate (optional)
        
        Returns:
            True if allowed, False if rate limited
        """
        now = time.time()
        bucket_key = f"ratelimit:{key}"
        
        # Use provided overrides or defaults
        bucket_size_to_use = bucket_size if bucket_size is not None else self.bucket_size
        refill_rate_to_use = refill_rate if refill_rate is not None else self.refill_rate
        
        # Get current bucket state
        pipe = self.redis_client.pipeline()
        pipe.hget(bucket_key, "tokens")
        pipe.hget(bucket_key, "last_refill")
        current_tokens, last_refill = pipe.execute()
        
        # Initialize if not exists
        if current_tokens is None:
            current_tokens = bucket_size_to_use
            last_refill = now
        else:
            current_tokens = float(current_tokens)
            last_refill = float(last_refill)
        
        # Refill tokens based on time elapsed
        elapsed = now - last_refill
        refill_amount = elapsed * refill_rate_to_use
        current_tokens = min(bucket_size_to_use, current_tokens + refill_amount)
        
        # Check if enough tokens
        if current_tokens >= tokens:
            # Consume tokens
            current_tokens -= tokens
            pipe = self.redis_client.pipeline()
            pipe.hset(bucket_key, "tokens", current_tokens)
            pipe.hset(bucket_key, "last_refill", now)
            pipe.expire(bucket_key, 3600)  # TTL 1 hour
            pipe.execute()
            return True
        else:
            # Rate limited
            return False



























