/**
 * In-tab TTL + singleflight cache for hot public GETs.
 * Not for wallet/auth/user-private data.
 */

type Entry = { data: unknown; ts: number };
const store = new Map<string, Entry>();
const inflight = new Map<string, Promise<unknown>>();

/** Align with backend publicConfig TTL */
export const CLIENT_TTL = {
  publicConfig: 45_000,
  matchesList: 15_000,
  contestsList: 12_000,
  liveMatches: 4_000,
} as const;

export function clientCachePeek<T>(key: string, ttlMs: number): T | null {
  const hit = store.get(key);
  if (!hit || Date.now() - hit.ts >= ttlMs) return null;
  return hit.data as T;
}

export async function clientCacheGet<T>(
  key: string,
  ttlMs: number,
  loader: () => Promise<T>,
  force = false
): Promise<T> {
  if (!force) {
    const hit = store.get(key);
    if (hit && Date.now() - hit.ts < ttlMs) return hit.data as T;
    const pending = inflight.get(key);
    if (pending) return pending as Promise<T>;
  }

  const promise = loader()
    .then((data) => {
      store.set(key, { data, ts: Date.now() });
      return data;
    })
    .finally(() => {
      inflight.delete(key);
    });

  inflight.set(key, promise);
  return promise;
}

export function clientCacheInvalidate(prefix?: string): void {
  if (!prefix) {
    store.clear();
    return;
  }
  for (const key of store.keys()) {
    if (key.startsWith(prefix)) store.delete(key);
  }
}
