# backend/cache_manager.py
"""Caché global en memoria con refresco en segundo plano (igual que el dashboard de ventas)."""
import time
import threading
from typing import Any, Callable, Dict, Tuple

_CACHE: Dict[str, Tuple[float, Any]] = {}
_LOCK = threading.Lock()
_DEFAULT_TTL = 900  # 15 min


def _make_key(prefix: str, args: tuple) -> str:
    return prefix + ":" + "|".join(str(a) for a in args)


def cache_get_or_set(prefix: str, args: tuple, loader: Callable[[], Any], ttl: int = _DEFAULT_TTL) -> Any:
    key = _make_key(prefix, args)
    now = time.time()
    with _LOCK:
        hit = _CACHE.get(key)
        if hit and (now - hit[0] < ttl):
            return hit[1]
    value = loader()
    with _LOCK:
        _CACHE[key] = (now, value)
    return value


def cache_keys():
    with _LOCK:
        return list(_CACHE.keys())


def cache_refresh_existing(loader_for_key):
    for key in cache_keys():
        try:
            nuevo = loader_for_key(key)
            if nuevo is not None:
                with _LOCK:
                    _CACHE[key] = (time.time(), nuevo)
        except Exception as e:
            print(f"[cache refresh] {key}: {e}")


def cache_invalidate(prefix: str = None) -> None:
    with _LOCK:
        if prefix is None:
            _CACHE.clear()
        else:
            for k in list(_CACHE.keys()):
                if k.startswith(prefix + ":"):
                    del _CACHE[k]


def cache_stats() -> dict:
    with _LOCK:
        return {"entradas": len(_CACHE), "claves": list(_CACHE.keys())}


_background_started = False


def start_background_refresh(refresh_fn: Callable[[], None], interval: int = 900):
    global _background_started
    if _background_started:
        return
    _background_started = True

    def _loop():
        while True:
            time.sleep(interval)
            try:
                refresh_fn()
            except Exception as e:
                print(f"[background refresh] error: {e}")

    t = threading.Thread(target=_loop, daemon=True)
    t.start()
    print(f"[cache] refresco en segundo plano cada {interval}s iniciado")
