"""Translation Cache Manager.

Two-level caching (memory + file) organized by language pairs.
"""

import hashlib
import json
import logging
from pathlib import Path
from typing import Any, Dict, Optional

logger = logging.getLogger(__name__)


class TranslationCacheManager:
    """Manages translation caching with TTL and file persistence."""

    def __init__(
        self,
        cache_dir: Optional[str] = None,
        ttl_hours: int = 24,
        max_memory_size: int = 1000
    ):
        """
        Initialize translation cache manager.

        Args:
            cache_dir: Directory for file cache. Defaults to ~/.sdkrouter/cache/translator
            ttl_hours: Time-to-live for memory cache in hours
            max_memory_size: Maximum number of entries in memory cache
        """
        if cache_dir is None:
            default_cache_dir = Path.home() / ".sdkrouter" / "cache" / "translator"
        else:
            default_cache_dir = Path(cache_dir)

        default_cache_dir.mkdir(parents=True, exist_ok=True)

        self.cache_dir = default_cache_dir
        self.ttl_seconds = ttl_hours * 3600
        self.max_memory_size = max_memory_size

        # Simple in-memory cache (dict-based for minimal dependencies)
        self._memory_cache: Dict[str, str] = {}
        self._cache_order: list[str] = []

        logger.debug("Translation cache initialized: %s", self.cache_dir)

    def _get_cache_file(self, source_lang: str, target_lang: str) -> Path:
        """Get cache file path for language pair."""
        return self.cache_dir / f"{source_lang}-{target_lang}.json"

    def _get_text_hash(self, text: str) -> str:
        """Generate hash for text."""
        return hashlib.md5(text.encode('utf-8')).hexdigest()

    def _load_file_cache(self, source_lang: str, target_lang: str) -> Dict[str, Any]:
        """Load translations from file cache."""
        cache_file = self._get_cache_file(source_lang, target_lang)

        if not cache_file.exists():
            return {}

        try:
            with open(cache_file, encoding='utf-8') as f:
                return json.load(f)
        except (OSError, json.JSONDecodeError) as e:
            logger.warning("Failed to load cache file %s: %s", cache_file, e)
            return {}

    def _save_file_cache(self, source_lang: str, target_lang: str, cache_data: Dict[str, Any]):
        """Save translations to file cache."""
        cache_file = self._get_cache_file(source_lang, target_lang)

        try:
            cache_file.parent.mkdir(parents=True, exist_ok=True)
            with open(cache_file, 'w', encoding='utf-8') as f:
                json.dump(cache_data, f, ensure_ascii=False, indent=2)
        except OSError as e:
            logger.error("Failed to save cache file %s: %s", cache_file, e)

    def _evict_if_needed(self):
        """Evict oldest entries if memory cache is full."""
        while len(self._memory_cache) >= self.max_memory_size and self._cache_order:
            oldest_key = self._cache_order.pop(0)
            self._memory_cache.pop(oldest_key, None)

    def get(self, text: str, source_lang: str, target_lang: str) -> Optional[str]:
        """
        Get translation from cache.

        Args:
            text: Original text
            source_lang: Source language code
            target_lang: Target language code

        Returns:
            Cached translation or None
        """
        text_hash = self._get_text_hash(text)
        cache_key = f"{source_lang}-{target_lang}:{text_hash}"

        # Check memory cache first
        if cache_key in self._memory_cache:
            return self._memory_cache[cache_key]

        # Check file cache
        file_cache = self._load_file_cache(source_lang, target_lang)
        if text_hash in file_cache:
            translation = file_cache[text_hash]
            # Store in memory cache
            self._evict_if_needed()
            self._memory_cache[cache_key] = translation
            self._cache_order.append(cache_key)
            return translation

        return None

    def set(self, text: str, source_lang: str, target_lang: str, translation: str):
        """
        Store translation in cache.

        Args:
            text: Original text
            source_lang: Source language code
            target_lang: Target language code
            translation: Translated text
        """
        text_hash = self._get_text_hash(text)
        cache_key = f"{source_lang}-{target_lang}:{text_hash}"

        # Store in memory cache
        self._evict_if_needed()
        self._memory_cache[cache_key] = translation
        if cache_key not in self._cache_order:
            self._cache_order.append(cache_key)

        # Store in file cache
        file_cache = self._load_file_cache(source_lang, target_lang)
        file_cache[text_hash] = translation
        self._save_file_cache(source_lang, target_lang, file_cache)

        logger.debug("Cached translation: %s->%s (%d chars)", source_lang, target_lang, len(text))

    def clear(self, source_lang: Optional[str] = None, target_lang: Optional[str] = None):
        """
        Clear cache (all or specific language pair).

        Args:
            source_lang: Optional source language to clear
            target_lang: Optional target language to clear
        """
        if source_lang and target_lang:
            # Clear specific language pair
            cache_file = self._get_cache_file(source_lang, target_lang)
            if cache_file.exists():
                cache_file.unlink()

            # Clear from memory cache
            prefix = f"{source_lang}-{target_lang}:"
            keys_to_remove = [k for k in self._memory_cache.keys() if k.startswith(prefix)]
            for key in keys_to_remove:
                del self._memory_cache[key]
                if key in self._cache_order:
                    self._cache_order.remove(key)

            logger.info("Cleared cache for %s->%s", source_lang, target_lang)
        else:
            # Clear all caches
            self._memory_cache.clear()
            self._cache_order.clear()

            # Remove all cache files
            if self.cache_dir.exists():
                for cache_file in self.cache_dir.glob("*.json"):
                    cache_file.unlink()

            logger.info("Cleared all translation caches")

    def get_stats(self) -> Dict[str, Any]:
        """Get cache statistics."""
        stats = {
            'memory_cache_size': len(self._memory_cache),
            'cache_dir': str(self.cache_dir),
            'language_pairs': []
        }

        if self.cache_dir.exists():
            for cache_file in self.cache_dir.glob("*.json"):
                lang_pair = cache_file.stem
                parts = lang_pair.split('-')
                if len(parts) == 2:
                    file_cache = self._load_file_cache(parts[0], parts[1])
                    stats['language_pairs'].append({
                        'pair': lang_pair,
                        'translations': len(file_cache),
                        'file_size': cache_file.stat().st_size
                    })

        return stats
