import 'dart:convert';
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../utils/logger.dart';
import '../../features/authentication/data/models/user_role.dart';

/// UnionFlow Mobile - Gestionnaire de Cache Unique (DRY)
/// Gère le cache mémoire (L1) et disque (L2) avec SharedPreferences.
class DashboardCacheManager {
  static final Map<String, dynamic> _memoryCache = {};
  static final Map<String, DateTime> _cacheTimestamps = {};
  static SharedPreferences? _prefs;
  
  static const Duration _defaultExpiry = Duration(minutes: 15);

  static Future<void> initialize() async {
    _prefs = await SharedPreferences.getInstance();
    debugPrint('📦 DashboardCacheManager Initialisé');
  }

  static T? get<T>(String key) {
    // 1. Check mémoire
    if (_memoryCache.containsKey(key)) {
      final ts = _cacheTimestamps[key];
      if (ts != null && DateTime.now().difference(ts) < _defaultExpiry) {
        return _memoryCache[key] as T?;
      }
    }
    // 2. Check disque
    if (_prefs != null) {
      final jsonStr = _prefs!.getString('cache_$key');
      if (jsonStr != null) {
        try {
          final data = jsonDecode(jsonStr);
          _memoryCache[key] = data;
          _cacheTimestamps[key] = DateTime.now();
          return data as T?;
        } catch (e, st) {
          AppLogger.error('DashboardCacheManager.get: décodage JSON échoué pour key=$key', error: e, stackTrace: st);
        }
      }
    }
    return null;
  }

  static Future<void> set<T>(String key, T value) async {
    _memoryCache[key] = value;
    _cacheTimestamps[key] = DateTime.now();
    if (_prefs != null) {
      try {
        await _prefs!.setString('cache_$key', jsonEncode(value));
      } catch (e, st) {
        AppLogger.error('DashboardCacheManager.set: écriture disque échouée pour key=$key', error: e, stackTrace: st);
        rethrow;
      }
    }
  }

  static Future<void> invalidateForRole(UserRole role) async {
    _memoryCache.removeWhere((key, _) => key.contains(role.name));
    _cacheTimestamps.removeWhere((key, _) => key.contains(role.name));
    if (_prefs != null) {
      final keys = _prefs!.getKeys().where((k) => k.startsWith('cache_') && k.contains(role.name));
      for (final k in keys) {
        await _prefs!.remove(k);
      }
    }
    debugPrint('🗑️ Cache invalidé pour le rôle: ${role.displayName}');
  }

  static Future<void> clear() async {
    _memoryCache.clear();
    _cacheTimestamps.clear();
    if (_prefs != null) {
      final keys = _prefs!.getKeys().where((k) => k.startsWith('cache_'));
      for (final k in keys) {
        await _prefs!.remove(k);
      }
    }
    debugPrint('🧹 Cache vidé globalement');
  }

  /// Délégation instance pour l’injection de dépendances
  Future<void> setKey<T>(String key, T value) async => set<T>(key, value);

  /// Délégation instance pour l’injection de dépendances
  T? getKey<T>(String key) => get<T>(key);

  /// Statistiques du cache (entrées, etc.)
  Map<String, dynamic> getCacheStats() {
    final latest = _cacheTimestamps.isEmpty ? null : _cacheTimestamps.values.reduce((a, b) => a.isAfter(b) ? a : b);
    return {
      'entries': _memoryCache.length,
      'timestamp': latest?.toIso8601String(),
    };
  }
}
