"""
Simple caching utilities for API endpoints.
"""

import time
import hashlib
from functools import wraps
from typing import Any, Dict, Optional
from datetime import datetime


class SimpleCache:
    """Simple in-memory cache with TTL support"""

    def __init__(self, ttl_seconds: int = 300):
        self._cache: Dict[str, tuple[Any, float]] = {}
        self.ttl_seconds = ttl_seconds

    def get(self, key: str) -> Optional[Any]:
        """Get value from cache if not expired"""
        if key in self._cache:
            value, timestamp = self._cache[key]
            if time.time() - timestamp < self.ttl_seconds:
                return value
            else:
                # Clean up expired entry
                del self._cache[key]
        return None

    def set(self, key: str, value: Any):
        """Set value in cache with current timestamp"""
        self._cache[key] = (value, time.time())

    def clear(self):
        """Clear all cache entries"""
        self._cache.clear()

    def cleanup_expired(self):
        """Remove expired entries"""
        current_time = time.time()
        expired_keys = [
            k
            for k, (_, ts) in self._cache.items()
            if current_time - ts >= self.ttl_seconds
        ]
        for key in expired_keys:
            del self._cache[key]


# Global cache instances for different endpoints
_cross_object_cache = SimpleCache(
    ttl_seconds=300
)  # 5-minute cache for cross-object detection


def cache_key_for_cross_object(
    account_id: str, min_score: float, limit: int, initial_batch: int, load_more: bool
) -> str:
    """Generate cache key for cross-object detection endpoint"""
    # Include hour in cache key for hourly refresh
    cache_hour = datetime.now().strftime("%Y%m%d%H")

    # Create deterministic key
    key_parts = [
        account_id,
        str(min_score),
        str(limit),
        str(initial_batch),
        str(load_more),
        cache_hour,
    ]
    key_string = "|".join(key_parts)

    # Hash for consistent length
    return hashlib.md5(key_string.encode()).hexdigest()


def cached_cross_object_detection(func):
    """Decorator to cache cross-object detection results"""

    @wraps(func)
    async def wrapper(*args, **kwargs):
        # Extract parameters for cache key - MUST include account_id for security
        account_id = kwargs.get("account_id", None)
        if not account_id:
            # Never cache without account_id to prevent cross-tenant leakage
            return await func(*args, **kwargs)

        min_score = kwargs.get("min_score", 0.75)
        limit = kwargs.get("limit", 100)
        initial_batch = kwargs.get("initial_batch", 100)
        load_more = kwargs.get("load_more", False)

        # Generate cache key with account_id for tenant isolation
        cache_key = cache_key_for_cross_object(
            account_id, min_score, limit, initial_batch, load_more
        )

        # Check cache
        cached_result = _cross_object_cache.get(cache_key)
        if cached_result is not None:
            # Deep copy to prevent mutation
            import copy

            cached_result = copy.deepcopy(cached_result)
            # Add cache hit indicator to stats
            if isinstance(cached_result, dict) and "stats" in cached_result:
                cached_result["stats"]["from_cache"] = True
                cached_result["stats"]["cache_key"] = cache_key[:8] + "..."
            return cached_result

        # Call original function
        result = await func(*args, **kwargs)

        # Cache successful results
        if result and not (isinstance(result, dict) and "error" in result):
            _cross_object_cache.set(cache_key, result)
            if isinstance(result, dict) and "stats" in result:
                result["stats"]["from_cache"] = False

        return result

    return wrapper


def clear_cross_object_cache():
    """Clear the cross-object detection cache"""
    _cross_object_cache.clear()


def get_cache_stats():
    """Get statistics about cache usage"""
    _cross_object_cache.cleanup_expired()

    return {
        "cross_object_detection": {
            "entries": len(_cross_object_cache._cache),
            "ttl_seconds": _cross_object_cache.ttl_seconds,
        }
    }
