import hashlib
import json

from pathlib import Path
from typing  import Optional, Dict


def get_file_hash(content: str) -> str:
 """
 Returns SHA256 hash of the content.
 [C: tests/test_summary_cache.py:test_get_file_hash, tests/test_summary_cache.py:test_summary_cache]
 """
 return hashlib.sha256(content.encode("utf-8")).hexdigest()

class SummaryCache:
 """
 A hash-based cache for file summaries to avoid redundant processing.
 Invalidates when content hash changes.
 """
 def __init__(self, cache_file: Optional[str] = None, max_entries: int = 1000):
  if cache_file:
   self.cache_file = Path(cache_file)
  else:
   # Default relative to current working directory
   self.cache_file = Path(".slop_cache/summary_cache.json")
  self.max_entries = max_entries
  self.cache: Dict[str, Dict[str, str]] = {}
  self.load()

 def load(self) -> None:
  """
  Loads cache from disk.
  [C: src/tool_presets.py:ToolPresetManager._read_raw, src/workspace_manager.py:WorkspaceManager._load_file, tests/test_gui_phase3.py:test_create_track, tests/test_history_management.py:test_save_separation, tests/test_session_logging.py:test_open_session_creates_subdir_and_registry]
  """
  if self.cache_file.exists():
   try:
    with open(self.cache_file, "r", encoding="utf-8") as f:
     self.cache = json.load(f)
   except Exception:
    self.cache = {}

 def save(self) -> None:
  """Saves cache to disk."""
  try:
   self.cache_file.parent.mkdir(parents=True, exist_ok=True)
   with open(self.cache_file, "w", encoding="utf-8") as f:
    json.dump(self.cache, f, indent=1)
  except Exception:
   pass

 def get_summary(self, file_path: str, content_hash: str) -> Optional[str]:
  """
  Returns cached summary if hash matches, otherwise None.
  [C: tests/test_summary_cache.py:test_summary_cache, tests/test_summary_cache.py:test_summary_cache_lru]
  """
  entry = self.cache.get(file_path)
  if entry and entry.get("hash") == content_hash:
   # LRU: move to end
   val = self.cache.pop(file_path)
   self.cache[file_path] = val
   return val.get("summary")
  return None

 def set_summary(self, file_path: str, content_hash: str, summary: str) -> None:
  """
  Stores summary in cache and saves to disk.
  [C: tests/test_summary_cache.py:test_summary_cache, tests/test_summary_cache.py:test_summary_cache_lru]
  """
  if file_path in self.cache:
   self.cache.pop(file_path)
  self.cache[file_path] = {
   "hash": content_hash,
   "summary": summary
  }
  # Enforce LRU size limit
  while len(self.cache) > self.max_entries:
   # pop first item (oldest)
   first_key = next(iter(self.cache))
   self.cache.pop(first_key)
  self.save()

 def clear(self) -> None:
  """
  Clears the cache both in-memory and on disk.
  [C: tests/conftest.py:reset_ai_client]
  """
  self.cache.clear()
  if self.cache_file.exists():
   try:
    self.cache_file.unlink()
   except Exception:
    pass

 def get_stats(self) -> dict:
  """Returns dictionary of cache statistics."""
  size_bytes = 0
  if self.cache_file.exists():
   try:
    size_bytes = self.cache_file.stat().st_size
   except Exception:
    pass
  return {
   "entries": len(self.cache),
   "size_bytes": size_bytes
  }
