#!/usr/bin/env python3
"""Rate limiter for database queries to prevent spamming."""

import time
from pathlib import Path
from typing import Optional

from alfred_utils import print_debug


class RateLimiter:
    """
    Rate limiter for database queries to prevent spamming. In theory the
    Alfred queue delay will would prevent that, but I added this to be safe.
    """

    def __init__(
        self,
        min_interval: float = 1.0,
        cache_dir: Path = Path(".cache"),
        limiter_file: str = "rate_limit.txt",
    ):
        """Initialize rate limiter.

        Args:
            min_interval: Minimum seconds between operations
            cache_dir: Directory to store rate limit file
            limiter_file: Name of the rate limit file
        """
        self.min_interval = min_interval
        self.cache_dir = Path(cache_dir)
        self.limiter_file = self.cache_dir / limiter_file

        # Ensure cache directory exists
        self.cache_dir.mkdir(parents=True, exist_ok=True)

    def _get_last_run(self) -> Optional[float]:
        """Get timestamp of last run from file."""
        try:
            if self.limiter_file.exists():
                with open(self.limiter_file, "r") as f:
                    return float(f.read().strip())
        except (ValueError, IOError):
            pass
        return None

    def _set_last_run(self, timestamp: float) -> None:
        """Save timestamp of last run to file."""
        with open(self.limiter_file, "w") as f:
            f.write(str(timestamp))

    def should_throttle(self) -> tuple[bool, float]:
        """Check if operation should be throttled.

        Returns:
            Tuple of (should_throttle, seconds_to_wait)
        """
        current_time = time.time()
        last_run = self._get_last_run()

        if last_run is None:
            return False, 0

        elapsed = current_time - last_run
        if elapsed < self.min_interval:
            wait_time = self.min_interval - elapsed
            return True, wait_time

        return False, 0

    def wait_if_needed(self) -> bool:
        """Wait if rate limit requires it.

        Returns:
            True if we had to wait, False otherwise
        """
        should_wait, wait_time = self.should_throttle()
        if should_wait:
            print_debug(f"Rate limiting: waiting {wait_time:.1f}s")
            time.sleep(wait_time)
            return True
        return False

    def record_operation(self) -> None:
        """Record that an operation just occurred."""
        self._set_last_run(time.time())

    def check_and_proceed(self) -> bool:
        """Combined check, wait, and record operation.

        Returns:
            True if operation can proceed (after any necessary wait)
        """
        self.wait_if_needed()
        self.record_operation()
        return True
