import asyncio
import time
from typing import Dict, Any

from rate_limiter.core.storage.backend import StorageBackend


class MemoryStorageBackend:
    """In-memory storage backend (not production-safe)."""

    def __init__(self):
        """Initialize in-memory storage backend."""
        self._data: Dict[str, tuple[int, float]] = {}  # key -> (value, expiry)
        self._lock = asyncio.Lock()

    async def incr(self, key: str, ttl: int) -> int:
        """
        Increment counter and return new value.

        Args:
            key: Storage key
            ttl: Time to live in seconds

        Returns:
            New counter value
        """
        async with self._lock:
            self._cleanup_expired()
            current_time = time.time()
            expiry = current_time + ttl

            if key in self._data:
                value, _ = self._data[key]
                new_value = value + 1
                self._data[key] = (new_value, expiry)
            else:
                new_value = 1
                self._data[key] = (new_value, expiry)

            return new_value

    async def get(self, key: str) -> int:
        """
        Get current counter value.

        Args:
            key: Storage key

        Returns:
            Current counter value (0 if key doesn't exist or expired)
        """
        async with self._lock:
            self._cleanup_expired()
            if key in self._data:
                value, _ = self._data[key]
                return value
            return 0

    async def set(self, key: str, value: int, ttl: int) -> None:
        """
        Set counter value.

        Args:
            key: Storage key
            value: Counter value
            ttl: Time to live in seconds
        """
        async with self._lock:
            self._cleanup_expired()
            current_time = time.time()
            expiry = current_time + ttl
            self._data[key] = (value, expiry)

    async def delete(self, key: str) -> None:
        """
        Delete a key.

        Args:
            key: Storage key
        """
        async with self._lock:
            if key in self._data:
                del self._data[key]

    async def exists(self, key: str) -> bool:
        """
        Check if key exists.

        Args:
            key: Storage key

        Returns:
            True if key exists and not expired, False otherwise
        """
        async with self._lock:
            self._cleanup_expired()
            return key in self._data

    async def ttl(self, key: str) -> int:
        """
        Get remaining TTL for a key.

        Args:
            key: Storage key

        Returns:
            Remaining TTL in seconds (-1 if key doesn't exist)
        """
        async with self._lock:
            self._cleanup_expired()
            if key not in self._data:
                return -1
            _, expiry = self._data[key]
            current_time = time.time()
            remaining = int(expiry - current_time)
            return max(0, remaining)

    async def close(self) -> None:
        """Close backend connection."""
        async with self._lock:
            self._data.clear()

    async def execute_script(self, script: str, keys: list[str], args: list) -> Any:
        """
        Execute Lua script (not supported in memory backend).

        Args:
            script: Lua script content
            keys: List of keys
            args: List of arguments

        Returns:
            None (not supported)
        """
        raise NotImplementedError("Lua scripts not supported in memory backend")

    def _cleanup_expired(self) -> None:
        """Remove expired keys."""
        current_time = time.time()
        expired_keys = [
            key for key, (_, expiry) in self._data.items() if expiry <= current_time
        ]
        for key in expired_keys:
            del self._data[key]
