import time
from typing import Tuple

from rate_limiter.core.algorithms.base import RateLimitAlgorithm
from rate_limiter.core.rules import RateLimitRule, Scope
from rate_limiter.core.storage.backend import StorageBackend


class FixedWindowAlgorithm:
    """Fixed window rate limiting algorithm."""

    async def allow(
        self,
        storage: StorageBackend,
        identity: str,
        rule: RateLimitRule,
        endpoint: str = "",
    ) -> Tuple[bool, int, int]:
        """
        Check if request should be allowed using fixed window.

        Args:
            storage: Storage backend
            identity: Request identity
            rule: Rate limit rule
            endpoint: Endpoint identifier

        Returns:
            Tuple of (allowed, remaining, retry_after)
        """
        # Create key based on scope
        # Include limit and window in key to ensure each rule has its own counter
        rule_id = f"{rule.limit}:{rule.window}"
        if rule.scope == Scope.GLOBAL:
            key = f"{rule.key}:{identity}:global:{rule_id}"
        elif rule.scope == Scope.ROUTER:
            key = f"{rule.key}:{identity}:router:{endpoint}:{rule_id}"
        else:  # endpoint
            key = f"{rule.key}:{identity}:endpoint:{endpoint}:{rule_id}"

        # Use window number as part of key to create fixed windows
        current_time = int(time.time())
        window_number = current_time // rule.window
        window_key = f"{key}:window:{window_number}"

        # Increment counter
        count = await storage.incr(window_key, rule.window)

        # Check if limit exceeded
        allowed = count <= rule.limit
        remaining = max(0, rule.limit - count)

        # Calculate retry_after (time until next window)
        retry_after = rule.window - (current_time % rule.window)

        return allowed, remaining, retry_after
