"""
Simple in-memory cache for Xero API responses to reduce rate limit usage.
Cache TTL: 10 minutes (configurable)
"""
import time
import logging
from typing import Any, Optional, Dict, Tuple
from datetime import datetime, timedelta

logger = logging.getLogger(__name__)


class XeroCache:
    """
    In-memory cache for Xero API responses.
    Stores responses with timestamps and auto-expires after TTL.
    """
    
    def __init__(self, ttl_minutes: int = 10):
        """
        Initialize cache with specified TTL.
        
        Args:
            ttl_minutes: Time-to-live in minutes (default: 10)
        """
        self._cache: Dict[str, Tuple[Any, float]] = {}  # {cache_key: (data, timestamp)}
        self._ttl_seconds = ttl_minutes * 60
        self._hits = 0
        self._misses = 0
        logger.info(f"✅ Xero cache initialized with {ttl_minutes} minute TTL")
    
    def get(self, cache_key: str) -> Optional[Any]:
        """
        Get cached data if available and not expired.
        
        Args:
            cache_key: Unique key for the cached data
            
        Returns:
            Cached data if valid, None if expired or not found
        """
        if cache_key not in self._cache:
            self._misses += 1
            return None
        
        data, timestamp = self._cache[cache_key]
        age_seconds = time.time() - timestamp
        
        if age_seconds > self._ttl_seconds:
            # Expired - remove from cache
            del self._cache[cache_key]
            self._misses += 1
            logger.debug(f"Cache MISS (expired): {cache_key} (age: {age_seconds:.0f}s)")
            return None
        
        self._hits += 1
        logger.debug(f"Cache HIT: {cache_key} (age: {age_seconds:.0f}s)")
        return data
    
    def set(self, cache_key: str, data: Any) -> None:
        """
        Store data in cache with current timestamp.
        
        Args:
            cache_key: Unique key for the data
            data: Data to cache
        """
        self._cache[cache_key] = (data, time.time())
        logger.debug(f"Cache SET: {cache_key}")
    
    def invalidate(self, cache_key: str) -> None:
        """
        Remove specific entry from cache.
        
        Args:
            cache_key: Key to invalidate
        """
        if cache_key in self._cache:
            del self._cache[cache_key]
            logger.debug(f"Cache INVALIDATE: {cache_key}")
    
    def clear(self) -> None:
        """Clear entire cache."""
        count = len(self._cache)
        self._cache.clear()
        self._hits = 0
        self._misses = 0
        logger.info(f"Cache CLEARED ({count} entries removed)")
    
    def get_stats(self) -> Dict[str, Any]:
        """
        Get cache statistics.
        
        Returns:
            Dict with hits, misses, hit_rate, size
        """
        total = self._hits + self._misses
        hit_rate = (self._hits / total * 100) if total > 0 else 0
        
        return {
            "hits": self._hits,
            "misses": self._misses,
            "hit_rate": f"{hit_rate:.1f}%",
            "cache_size": len(self._cache),
            "ttl_minutes": self._ttl_seconds / 60
        }
    
    def log_stats(self) -> None:
        """Log cache statistics."""
        stats = self.get_stats()
        logger.info(
            f"📊 Cache Stats: {stats['hits']} hits, {stats['misses']} misses "
            f"({stats['hit_rate']} hit rate), {stats['cache_size']} entries"
        )


# Singleton instance
xero_cache = XeroCache(ttl_minutes=10)
