/**
 * Service de cache pour optimiser les performances
 */

export interface CacheEntry<T> {
  data: T;
  timestamp: number;
  ttl: number; // Time to live en millisecondes
}

export class CacheService {
  private static cache = new Map<string, CacheEntry<any>>();
  private static readonly DEFAULT_TTL = 5 * 60 * 1000; // 5 minutes par défaut

  /**
   * Stocke une valeur dans le cache
   */
  static set<T>(key: string, data: T, ttl: number = this.DEFAULT_TTL): void {
    const entry: CacheEntry<T> = {
      data,
      timestamp: Date.now(),
      ttl
    };
    this.cache.set(key, entry);
  }

  /**
   * Récupère une valeur du cache
   */
  static get<T>(key: string): T | null {
    const entry = this.cache.get(key);
    
    if (!entry) {
      return null;
    }

    // Vérifier si l'entrée a expiré
    if (Date.now() - entry.timestamp > entry.ttl) {
      this.cache.delete(key);
      return null;
    }

    return entry.data as T;
  }

  /**
   * Supprime une entrée du cache
   */
  static delete(key: string): boolean {
    return this.cache.delete(key);
  }

  /**
   * Vide tout le cache
   */
  static clear(): void {
    this.cache.clear();
  }

  /**
   * Nettoie les entrées expirées
   */
  static cleanup(): void {
    const now = Date.now();
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > entry.ttl) {
        this.cache.delete(key);
      }
    }
  }

  /**
   * Récupère ou exécute une fonction avec mise en cache
   */
  static async getOrSet<T>(
    key: string,
    fetchFunction: () => Promise<T>,
    ttl: number = this.DEFAULT_TTL
  ): Promise<T> {
    // Essayer de récupérer depuis le cache
    const cached = this.get<T>(key);
    if (cached !== null) {
      return cached;
    }

    // Exécuter la fonction et mettre en cache
    try {
      const data = await fetchFunction();
      this.set(key, data, ttl);
      return data;
    } catch (error) {
      // Ne pas mettre en cache les erreurs
      throw error;
    }
  }

  /**
   * Invalide le cache pour un pattern de clés
   */
  static invalidatePattern(pattern: string): void {
    const regex = new RegExp(pattern);
    for (const key of this.cache.keys()) {
      if (regex.test(key)) {
        this.cache.delete(key);
      }
    }
  }

  /**
   * Obtient les statistiques du cache
   */
  static getStats(): {
    size: number;
    keys: string[];
    expired: number;
  } {
    const now = Date.now();
    let expired = 0;
    
    for (const [key, entry] of this.cache.entries()) {
      if (now - entry.timestamp > entry.ttl) {
        expired++;
      }
    }

    return {
      size: this.cache.size,
      keys: Array.from(this.cache.keys()),
      expired
    };
  }
}

// Nettoyage automatique toutes les 10 minutes
if (typeof window !== 'undefined') {
  setInterval(() => {
    CacheService.cleanup();
  }, 10 * 60 * 1000);
}

// Clés de cache prédéfinies
export const CacheKeys = {
  CLIENTS: 'clients',
  CHANTIERS: 'chantiers',
  DEVIS: 'devis',
  FACTURES: 'factures',
  DASHBOARD_STATS: 'dashboard_stats',
  USER_PROFILE: 'user_profile',
  
  // Fonctions utilitaires pour générer des clés
  clientById: (id: string) => `client_${id}`,
  chantierId: (id: string) => `chantier_${id}`,
  devisById: (id: string) => `devis_${id}`,
  factureById: (id: string) => `facture_${id}`,
  devisByClient: (clientId: string) => `devis_client_${clientId}`,
  facturesByClient: (clientId: string) => `factures_client_${clientId}`,
} as const;
