import { deepEqual } from '@/utils/deepEqual'
import { executeRequest } from './executeRequest'

const cacheStore = new Map()

/**
 * Cache-first, stale-while-revalidate data fetcher.
 *
 * Supports:
 * - URL string (GET)
 * - Request object (GET / POST)
 * - Custom async fetcher function
 *
 * @param {Object} options
 * @param {string} options.key - Unique cache key
 * @param {string|Object} [options.request] - URL or request config
 * @param {Function} [options.fetcher] - Custom async function
 * @param {Function} options.onUpdate - Callback with data
 *
 * @example
 * fetchWithCache({
 *   key: 'users.list',
 *   request: '/api/users',
 *   onUpdate: (data, source) => {
 *     users.value = data
 *   }
 * })
 */
export async function fetchWithCache({
  key,
  request = null,
  fetcher = null,
  onUpdate = null
}) {
  if (!key) {
    throw new Error('fetchWithCache requires a cache key')
  }

  // 1️⃣ Emit cached data immediately
  if (cacheStore.has(key)) {
    onUpdate?.(cacheStore.get(key), 'cache')
  }

  // 2️⃣ Build fetcher if not provided
  let resolvedFetcher = fetcher

  if (!resolvedFetcher && request) {
    resolvedFetcher = () => executeRequest(request)
  }

  if (typeof resolvedFetcher !== 'function') {
    throw new Error('fetchWithCache requires either fetcher or request')
  }

  // 3️⃣ Fetch fresh data
  try {
    const fresh = await resolvedFetcher()
    const cached = cacheStore.get(key)

    if (!cached || !deepEqual(cached, fresh)) {
      cacheStore.set(key, fresh)
      onUpdate?.(fresh, 'fresh')
    }
  } catch (err) {
    console.error('[fetchWithCache] fetch failed:', err)
  }
}
