/**
 * Reusable Cache Manager Utility
 * Provides localStorage-based caching with expiration support
 * Can be used across all Pinia stores without code duplication
 */

export class CacheManager {
  constructor(prefix = 'cache_', duration = 10 * 60 * 1000) {
    this.prefix = prefix
    this.duration = duration // Default: 10 minutes
  }

  /**
   * Generate a unique cache key based on parameters
   * @param {Object} params - Parameters to include in cache key
   * @returns {string} - Generated cache key
   */
  generateKey(params = {}) {
    const keys = Object.keys(params).sort()
    const keyString = keys
      .map(key => `${key}:${params[key] ?? 'none'}`)
      .join('_')
    return `${this.prefix}${keyString}`
  }

  /**
   * Save data to cache with timestamp and expiry
   * @param {string} key - Cache key
   * @param {*} data - Data to cache
   */
  save(key, data) {
    try {
      const cacheData = {
        data,
        timestamp: Date.now(),
        expiry: Date.now() + this.duration
      }
      localStorage.setItem(key, JSON.stringify(cacheData))
    } catch (error) {
      console.warn('Failed to save to cache:', error)
    }
  }

  /**
   * Load data from cache if not expired
   * @param {string} key - Cache key
   * @returns {*|null} - Cached data or null if expired/not found
   */
  load(key) {
    try {
      const cached = localStorage.getItem(key)
      if (!cached) return null

      const cacheData = JSON.parse(cached)
      const now = Date.now()

      // Check if cache has expired
      if (now > cacheData.expiry) {
        localStorage.removeItem(key)
        return null
      }

      return cacheData.data
    } catch (error) {
      console.warn('Failed to load from cache:', error)
      return null
    }
  }

  /**
   * Remove a specific cache entry
   * @param {string} key - Cache key to remove
   */
  remove(key) {
    try {
      localStorage.removeItem(key)
    } catch (error) {
      console.warn('Failed to remove cache:', error)
    }
  }

  /**
   * Clear all caches with this prefix
   */
  clearAll() {
    try {
      const keys = Object.keys(localStorage)
      keys.forEach(key => {
        if (key.startsWith(this.prefix)) {
          localStorage.removeItem(key)
        }
      })
    } catch (error) {
      console.warn('Failed to clear all caches:', error)
    }
  }

  /**
   * Clear only expired cache entries
   */
  clearExpired() {
    try {
      const keys = Object.keys(localStorage)
      const now = Date.now()
      
      keys.forEach(key => {
        if (key.startsWith(this.prefix)) {
          try {
            const cached = JSON.parse(localStorage.getItem(key))
            if (cached && now > cached.expiry) {
              localStorage.removeItem(key)
            }
          } catch (e) {
            localStorage.removeItem(key)
          }
        }
      })
    } catch (error) {
      console.warn('Failed to clear expired caches:', error)
    }
  }

  /**
   * Check if a cache key exists and is valid
   * @param {string} key - Cache key
   * @returns {boolean}
   */
  has(key) {
    return this.load(key) !== null
  }

  /**
   * Get cache statistics
   * @returns {Object} - Cache statistics
   */
  getStats() {
    try {
      const keys = Object.keys(localStorage)
      const cacheKeys = keys.filter(key => key.startsWith(this.prefix))
      const now = Date.now()
      
      let valid = 0
      let expired = 0
      let totalSize = 0

      cacheKeys.forEach(key => {
        try {
          const value = localStorage.getItem(key)
          totalSize += value.length
          
          const cached = JSON.parse(value)
          if (now > cached.expiry) {
            expired++
          } else {
            valid++
          }
        } catch (e) {
          expired++
        }
      })

      return {
        total: cacheKeys.length,
        valid,
        expired,
        size: `${(totalSize / 1024).toFixed(2)} KB`
      }
    } catch (error) {
      console.warn('Failed to get cache stats:', error)
      return { total: 0, valid: 0, expired: 0, size: '0 KB' }
    }
  }
}

/**
 * Factory function to create cache manager instances for different stores
 * @param {string} storeName - Name of the store (e.g., 'teachers', 'programs')
 * @param {number} duration - Cache duration in milliseconds (optional)
 * @returns {CacheManager}
 */
export function createCacheManager(storeName, duration) {
  return new CacheManager(`${storeName}_cache_`, duration)
}
