"""Generic caching in .slices cache dir."""

from dataclasses import dataclass
from datetime import datetime, timedelta
from pathlib import Path

from pytz import UTC

from slices_clientlib_core.base.config import cache_dir_location


@dataclass
class CacheEntry:
    """Cache Entry."""

    entry_type: str
    entry_id: str
    content: str
    cached_at: datetime
    location: Path


def _cache_file_location(entry_type: str, entry_id: str) -> Path:
    return cache_dir_location / f"cache_{entry_type}_{entry_id}"


def load_cache_entry(entry_type: str, entry_id: str, ttl: timedelta) -> CacheEntry | None:
    """Get a cache entry, if present."""

    try:
        cache_file_location = _cache_file_location(entry_type, entry_id)
        if not cache_file_location.exists():
            return None

        modify_time = datetime.fromtimestamp(cache_file_location.stat().st_mtime, tz=UTC)
        if modify_time < datetime.now(UTC) - ttl:
            return None

        with cache_file_location.open() as cache_file:
            return CacheEntry(
                entry_type=entry_type,
                entry_id=entry_id,
                content=cache_file.read(),
                cached_at=modify_time,
                location=cache_file_location,
            )
    except:  # noqa E722
        # Ignore failures reading from cache.
        # This will cause silent fall back to not caching.
        return None


def save_cache_entry(entry_type: str, entry_id: str, content: str | bytes):
    """Save entry to the cache."""

    try:
        with _cache_file_location(entry_type, entry_id).open("wb") as cache_file:
            cache_file.write(content.encode() if isinstance(content, str) else content)
    except:  # noqa E722
        # Ignore failures writing to cache.
        # This will cause silent fall back to not caching.
        pass


def clear_cache_entry(entry_type: str, entry_id: str):
    """Clear cache entry."""

    cache_entry_path = _cache_file_location(entry_type, entry_id)
    cache_entry_path.unlink(missing_ok=True)
