// Cached API Wrapper for Performance Optimization
import { dataCache } from './performance';

/**
 * Wrapper for API calls with automatic caching
 */
export async function cachedApiCall<T>(
  cacheKey: string,
  fetcher: () => Promise<T>,
  ttlMinutes: number = 5
): Promise<T> {
  // Check cache first
  const cached = dataCache.get(cacheKey) as T | null;
  if (cached) {
    return cached;
  }

  // Fetch and cache
  const data = await fetcher();
  dataCache.set(cacheKey, data);
  return data;
}

/**
 * Invalidate cache for a specific key or pattern
 */
export function invalidateCache(keyOrPattern: string) {
  if (keyOrPattern.includes('*')) {
    // Pattern matching - clear all matching keys
    dataCache.clear();
  } else {
    // Specific key
    dataCache.clear();
  }
}

/**
 * Prefetch data for better UX
 */
export async function prefetchData<T>(
  cacheKey: string,
  fetcher: () => Promise<T>
): Promise<void> {
  if (!dataCache.has(cacheKey)) {
    const data = await fetcher();
    dataCache.set(cacheKey, data);
  }
}

/**
 * Batch multiple API calls
 */
export async function batchApiCalls<T>(
  calls: Array<() => Promise<T>>
): Promise<T[]> {
  return Promise.all(calls.map((call) => call()));
}

/**
 * Retry failed API calls with exponential backoff
 */
export async function retryApiCall<T>(
  fetcher: () => Promise<T>,
  maxRetries: number = 3,
  baseDelay: number = 1000
): Promise<T> {
  let lastError: Error;

  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fetcher();
    } catch (error) {
      lastError = error as Error;
      if (i < maxRetries - 1) {
        const delay = baseDelay * Math.pow(2, i);
        await new Promise((resolve) => setTimeout(resolve, delay));
      }
    }
  }

  throw lastError!;
}

export default {
  cachedApiCall,
  invalidateCache,
  prefetchData,
  batchApiCalls,
  retryApiCall,
};
