"""
MuBit Learn Lesson Cache.

Thread-safe TTL cache for get_context() results to avoid round-trips
on rapid sequential LLM calls within the same session.
"""

import hashlib
import threading
import time
from typing import Dict, Optional, Tuple


class LessonCache:
    """TTL-bounded in-process cache keyed by (session_id, query_hash)."""

    def __init__(self, ttl_seconds: float = 30.0, max_entries: int = 100):
        self._store: Dict[str, Tuple[float, str]] = {}
        self._ttl = ttl_seconds
        self._max = max_entries
        self._lock = threading.Lock()

    def get(self, session_id: str, query: str) -> Optional[str]:
        """Return cached context_block or None on miss/expiry."""
        key = self._key(session_id, query)
        with self._lock:
            entry = self._store.get(key)
            if entry and (time.monotonic() - entry[0]) < self._ttl:
                return entry[1]
            if entry:
                del self._store[key]
            return None

    def set(self, session_id: str, query: str, context_block: str) -> None:
        """Store a context_block with TTL."""
        key = self._key(session_id, query)
        with self._lock:
            if len(self._store) >= self._max:
                oldest_key = min(self._store, key=lambda k: self._store[k][0])
                del self._store[oldest_key]
            self._store[key] = (time.monotonic(), context_block)

    def clear(self) -> None:
        """Clear all cached entries."""
        with self._lock:
            self._store.clear()

    @staticmethod
    def _key(session_id: str, query: str) -> str:
        qh = hashlib.md5(query.encode("utf-8", errors="replace")).hexdigest()[:12]
        return f"{session_id}:{qh}"
