"""File-based TTL cache for API responses."""
from __future__ import annotations

import hashlib
import json
import logging
import time
from pathlib import Path

logger = logging.getLogger("dattos_sdk")


class FileCache:
    """Simple file-based cache with TTL expiration."""

    def __init__(self, cache_dir: Path):
        self.cache_dir = cache_dir
        self.cache_dir.mkdir(parents=True, exist_ok=True)

    def _cache_key(self, path: str, params: dict | None) -> str:
        """Generate deterministic cache key from path and params."""
        raw = f"{path}:{sorted(params.items()) if params else ''}"
        return hashlib.sha256(raw.encode()).hexdigest()

    def get(self, path: str, params: dict | None) -> dict | list | None:
        """Return cached response if valid, None if expired/missing."""
        key = self._cache_key(path, params)
        cache_file = self.cache_dir / f"{key}.json"
        if not cache_file.exists():
            return None
        try:
            data = json.loads(cache_file.read_text())
            if time.time() > data["expires"]:
                cache_file.unlink(missing_ok=True)
                return None
            return data["data"]
        except (json.JSONDecodeError, KeyError, OSError):
            cache_file.unlink(missing_ok=True)
            return None

    def set(self, path: str, params: dict | None, data: dict | list, ttl: int) -> None:
        """Write response to cache with TTL."""
        key = self._cache_key(path, params)
        cache_file = self.cache_dir / f"{key}.json"
        entry = {"expires": time.time() + ttl, "data": data, "path": path}
        try:
            cache_file.write_text(json.dumps(entry))
        except OSError as e:
            logger.debug("Cache write failed: %s", e)

    def invalidate(self, pattern: str) -> None:
        """Remove cache entries matching a path pattern."""
        for cache_file in self.cache_dir.glob("*.json"):
            try:
                entry = json.loads(cache_file.read_text())
                if entry.get("path", "").startswith(pattern):
                    cache_file.unlink(missing_ok=True)
            except (json.JSONDecodeError, KeyError, OSError):
                cache_file.unlink(missing_ok=True)

    def clear(self) -> None:
        """Remove all cache entries."""
        for cache_file in self.cache_dir.glob("*.json"):
            cache_file.unlink(missing_ok=True)
