import 'dart:async';
import 'dart:io';
import 'dart:js' as js;
import 'package:geosector_app/core/services/hive_web_fix.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:path_provider/path_provider.dart';
import 'package:geosector_app/core/constants/app_keys.dart';
import 'package:geosector_app/core/services/api_service.dart';
import 'package:geosector_app/core/services/sync_service.dart';
import 'package:geosector_app/core/services/hive_reset_state_service.dart';
import 'package:geosector_app/core/data/models/user_model.dart';
import 'package:geosector_app/core/data/models/amicale_model.dart';
import 'package:geosector_app/core/data/models/operation_model.dart';
import 'package:geosector_app/core/data/models/sector_model.dart';
import 'package:geosector_app/core/data/models/passage_model.dart';
import 'package:geosector_app/core/data/models/membre_model.dart';
import 'package:geosector_app/core/data/models/user_sector_model.dart';
import 'package:geosector_app/core/repositories/operation_repository.dart';
import 'package:geosector_app/core/repositories/sector_repository.dart';
import 'package:geosector_app/core/repositories/passage_repository.dart';
import 'package:geosector_app/core/repositories/client_repository.dart';
import 'package:geosector_app/core/repositories/amicale_repository.dart';
import 'package:geosector_app/chat/models/conversation_model.dart';
import 'package:geosector_app/chat/models/message_model.dart';
import 'package:geosector_app/presentation/widgets/loading_overlay.dart';
import 'package:geosector_app/presentation/widgets/loading_progress_overlay.dart';
import 'package:geosector_app/core/models/loading_state.dart';

class UserRepository extends ChangeNotifier {
  // Contrôle de l'état du chargement des données
  LoadingState _loadingState = LoadingState.initial;
  LoadingState get loadingState => _loadingState;

  // Overlay pour afficher la progression du chargement
  OverlayEntry? _progressOverlay;

  // Méthode pour mettre à jour l'état du chargement
  void _updateLoadingState(LoadingState newState) {
    _loadingState = newState;
    notifyListeners();

    // Mettre à jour l'overlay si présent
    if (_progressOverlay != null) {
      _progressOverlay!.markNeedsBuild();
    }
  }

  // Utilisation de getters lazy pour n'accéder aux boîtes que lorsque nécessaire
  Box<UserModel> get _userBox => Hive.box<UserModel>(AppKeys.usersBoxName);
  Box<AmicaleModel> get _amicaleBox =>
      Hive.box<AmicaleModel>(AppKeys.amicaleBoxName);

  // Getters pour les autres boîtes qui vérifient si elles sont ouvertes avant accès
  Box<OperationModel> get _operationBox {
    _ensureBoxIsOpen(AppKeys.operationsBoxName);
    return Hive.box<OperationModel>(AppKeys.operationsBoxName);
  }

  Box<SectorModel> get _sectorBox {
    _ensureBoxIsOpen(AppKeys.sectorsBoxName);
    return Hive.box<SectorModel>(AppKeys.sectorsBoxName);
  }

  Box<PassageModel> get _passageBox {
    _ensureBoxIsOpen(AppKeys.passagesBoxName);
    return Hive.box<PassageModel>(AppKeys.passagesBoxName);
  }

  Box<MembreModel> get _membreBox {
    _ensureBoxIsOpen(AppKeys.membresBoxName);
    return Hive.box<MembreModel>(AppKeys.membresBoxName);
  }

  Box<UserSectorModel> get _userSectorBox {
    _ensureBoxIsOpen(AppKeys.userSectorBoxName);
    return Hive.box<UserSectorModel>(AppKeys.userSectorBoxName);
  }

  Box get _settingsBox {
    _ensureBoxIsOpen(AppKeys.settingsBoxName);
    return Hive.box(AppKeys.settingsBoxName);
  }

  Box<ConversationModel> get _chatConversationBox {
    _ensureBoxIsOpen(AppKeys.chatConversationsBoxName);
    return Hive.box<ConversationModel>(AppKeys.chatConversationsBoxName);
  }

  Box<MessageModel> get _chatMessageBox {
    _ensureBoxIsOpen(AppKeys.chatMessagesBoxName);
    return Hive.box<MessageModel>(AppKeys.chatMessagesBoxName);
  }

  // Méthode pour initialiser les boîtes après connexion
  Future<void> _initializeBoxes() async {
    debugPrint('Initialisation des boîtes Hive nécessaires...');
    await _ensureBoxIsOpen(AppKeys.amicaleBoxName);
    await _ensureBoxIsOpen(AppKeys.operationsBoxName);
    await _ensureBoxIsOpen(AppKeys.sectorsBoxName);
    await _ensureBoxIsOpen(AppKeys.passagesBoxName);
    await _ensureBoxIsOpen(AppKeys.membresBoxName);
    await _ensureBoxIsOpen(AppKeys.userSectorBoxName);
    // Les boîtes de chat sont déjà initialisées au démarrage
    await _ensureBoxIsOpen(AppKeys.chatConversationsBoxName);
    await _ensureBoxIsOpen(AppKeys.chatMessagesBoxName);
    debugPrint('Toutes les boîtes Hive sont maintenant ouvertes');
  }

  final ApiService _apiService;
  final SyncService? _syncService;
  final OperationRepository? _operationRepository;
  final SectorRepository? _sectorRepository;
  final PassageRepository? _passageRepository;

  bool _isLoading = false;

  UserRepository(this._apiService,
      {SyncService? syncService,
      OperationRepository? operationRepository,
      SectorRepository? sectorRepository,
      PassageRepository? passageRepository})
      : _syncService = syncService,
        _operationRepository = operationRepository,
        _sectorRepository = sectorRepository,
        _passageRepository = passageRepository {
    // Initialiser la session si un utilisateur est déjà connecté
    final currentUser = getCurrentUser();
    if (currentUser != null && currentUser.sessionId != null) {
      setSessionId(currentUser.sessionId);
    }
  }

  // Cache pour l'utilisateur actuel
  UserModel? _cachedCurrentUser;

  // Getters
  bool get isLoading => _isLoading;
  bool get isLoggedIn => currentUser != null;
  int? get userId => currentUser?.id;
  UserModel? get currentUser {
    // Utiliser le cache s'il existe déjà
    if (_cachedCurrentUser != null) {
      return _cachedCurrentUser;
    }

    // Sinon, récupérer l'utilisateur et le mettre en cache
    _cachedCurrentUser = _getCurrentUserFromStorage();
    return _cachedCurrentUser;
  }

  // Retourne le rôle de l'utilisateur sous forme d'entier
  int getUserRole() {
    final user = getCurrentUser();
    if (user == null) return 0; // Aucun utilisateur = aucun rôle

    // Convertir le rôle en int si c'est une String
    if (user.role is String) {
      return int.tryParse(user.role as String) ?? 1;
    } else {
      return user.role as int;
    }
  }

  // Méthode privée pour récupérer l'utilisateur depuis le stockage
  UserModel? _getCurrentUserFromStorage() {
    try {
      // Vérifier d'abord si la boîte est ouverte
      if (!Hive.isBoxOpen(AppKeys.usersBoxName)) {
        try {
          Hive.openBox<UserModel>(AppKeys.usersBoxName);
        } catch (e) {
          debugPrint(
              'Erreur lors de l\'ouverture de la boîte utilisateurs: $e');
          return null;
        }
      }

      // Chercher un utilisateur avec une session active - Il suffit qu'il ait un sessionId
      final activeUsers = _userBox.values
          .where((user) =>
              user.sessionId != null && // Vérifier que sessionId n'est pas null
              user.sessionId!
                  .isNotEmpty) // Vérifier que sessionId n'est pas vide
          .toList();

      // S'il y a des utilisateurs actifs, retourner le premier
      if (activeUsers.isNotEmpty) {
        return activeUsers.first;
      }

      return null;
    } catch (e) {
      debugPrint(
          'Erreur lors de la récupération de l\'utilisateur depuis le stockage: $e');
      return null;
    }
  }

  // Récupérer l'utilisateur actuellement connecté
  UserModel? getCurrentUser() {
    // Utiliser le getter currentUser qui gère le cache
    return currentUser;
  }

  // Mettre à jour le chemin de la page actuelle pour l'utilisateur connecté
  Future<void> updateLastPath(String path) async {
    final currentUser = getCurrentUser();
    if (currentUser != null) {
      final updatedUser = currentUser.copyWith(lastPath: path);
      await saveUser(updatedUser);
    }
  }

  // Récupérer le dernier chemin visité par l'utilisateur
  String? getLastPath() {
    final currentUser = getCurrentUser();
    return currentUser?.lastPath;
  }

  // Configurer la session dans l'API
  void setSessionId(String? sessionId) {
    _apiService.setSessionId(sessionId);
  }

  // Login API PHP
  Future<Map<String, dynamic>> loginAPI(String username, String password,
      {required String type}) async {
    try {
      return await _apiService.login(username, password, type: type);
    } catch (e) {
      debugPrint('Erreur login API: $e');
      rethrow;
    }
  }

  // Register API PHP - Uniquement pour les administrateurs
  Future<Map<String, dynamic>> registerAPI(String email, String name,
      String amicaleName, String postalCode, String cityName) async {
    try {
      final Map<String, dynamic> data = {
        'email': email,
        'name': name,
        'amicale_name': amicaleName,
        'postal_code': postalCode,
        'city_name': cityName
      };

      final response =
          await _apiService.post(AppKeys.registerEndpoint, data: data);
      return response.data;
    } catch (e) {
      debugPrint('Erreur register API: $e');
      rethrow;
    }
  }

  // Logout API PHP
  Future<void> logoutAPI() async {
    try {
      await _apiService.logout();
    } catch (e) {
      debugPrint('Erreur logout API: $e');
      rethrow;
    }
  }

  // Méthode d'inscription (uniquement pour les administrateurs)
  Future<bool> register(String email, String password, String name,
      String amicaleName, String postalCode, String cityName) async {
    _isLoading = true;
    notifyListeners();

    try {
      // Enregistrer l'administrateur via l'API
      final apiResult =
          await registerAPI(email, name, amicaleName, postalCode, cityName);

      // Créer l'administrateur local
      final int userId = apiResult['user_id'] is String
          ? int.parse(apiResult['user_id'])
          : apiResult['user_id'];
      final now = DateTime.now();
      final newAdmin = UserModel(
        id: userId,
        email: email,
        name: name,
        role: AppKeys.roleAdmin2,
        createdAt: now,
        lastSyncedAt: now,
        isActive: true,
        isSynced: true,
        sessionId: apiResult['session_id'],
        sessionExpiry: DateTime.parse(apiResult['session_expiry']),
      );

      // Sauvegarder dans le repository local
      await saveUser(newAdmin);

      // Configurer la session dans l'API
      setSessionId(newAdmin.sessionId);

      notifyListeners();
      return true;
    } catch (e) {
      debugPrint('Erreur d\'inscription: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Login complet avec suivi de progression
  Future<bool> login(String username, String password,
      {required String type}) async {
    _isLoading = true;
    _updateLoadingState(LoadingState.initial.copyWith(
      message: 'Connexion en cours...',
      stepDescription: 'Préparation des données',
    ));
    notifyListeners();

    try {
      debugPrint('Début du processus de connexion pour: $username');

      // Étape 1: Nettoyage des boîtes non référencées (5%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.05,
        stepDescription: 'Nettoyage des données obsolètes',
      ));

      final nonDefinedBoxes = ['auth', 'locations', 'messages'];
      for (final boxName in nonDefinedBoxes) {
        try {
          if (Hive.isBoxOpen(boxName)) {
            debugPrint('Fermeture de la boîte non référencée: $boxName');
            await Hive.box(boxName).close();
          }

          // Supprimer la boîte du disque
          await Hive.deleteBoxFromDisk(boxName);
          debugPrint('Nettoyage: Box $boxName supprimée');
        } catch (e) {
          debugPrint(
              'Erreur lors de la suppression de la boîte non référencée $boxName: $e');
        }
      }

      // Étape 2: Nettoyage des données existantes (10%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.10,
        stepDescription: 'Préparation du stockage local',
      ));

      debugPrint('Nettoyage des données existantes avant connexion...');

      // Sur le web, utiliser notre méthode sécurisée pour nettoyer les boîtes Hive
      if (kIsWeb) {
        await HiveWebFix.safeCleanHiveBoxes(
            excludeBoxes: [AppKeys.usersBoxName]);
      }
      // Sur iOS, nettoyer les fichiers Hive directement
      else if (!kIsWeb && Platform.isIOS) {
        await _cleanHiveFilesOnIOS();
      }
      // Sur Android, nettoyer les fichiers Hive directement
      else if (!kIsWeb && Platform.isAndroid) {
        await _cleanHiveFilesOnAndroid();
      }

      // Étape 3: Recréation des boîtes (15%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.15,
        stepDescription: 'Initialisation des bases de données',
      ));

      // Nettoyer les boîtes sans les fermer
      await _clearAndRecreateBoxes();

      // Initialiser les boîtes nécessaires avant d'appeler l'API
      // Cela garantit que toutes les boîtes sont ouvertes avant le traitement des données
      await _initializeBoxes();

      // Étape 4: Connexion à l'API (25%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.25,
        stepDescription: 'Connexion au serveur',
      ));

      // Appeler l'API
      debugPrint('Appel de l\'API de connexion (type: $type)...');
      final apiResult = await loginAPI(username, password, type: type);

      // Vérifier le statut de la réponse
      final status = apiResult['status'] as String?;
      final message = apiResult['message'] as String?;

      // Si le statut n'est pas 'success', retourner false
      if (status != 'success') {
        debugPrint('Échec de connexion: $message');
        _updateLoadingState(
            LoadingState.error(message ?? 'Échec de connexion'));
        return false;
      }

      // Étape 5: Traitement des données utilisateur (35%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.35,
        stepDescription: 'Traitement des données utilisateur',
      ));

      // Logging détaillé de la réponse API pour diagnostiquer le problème d'interface/rôle
      debugPrint('Connexion réussie, contenu de la réponse API:');
      apiResult.forEach((key, value) {
        debugPrint('   $key: $value');
      });

      // Si la clé 'user' existe, examiner son contenu
      if (apiResult['user'] != null &&
          apiResult['user'] is Map<String, dynamic>) {
        debugPrint('Détails utilisateur:');
        final userDetails = apiResult['user'] as Map<String, dynamic>;
        userDetails.forEach((key, value) {
          debugPrint('   $key: $value (${value.runtimeType})');
        });

        // Construire un UserModel à partir des données utilisateur
        final user = _processUserData(
            userDetails, apiResult['session_id'], apiResult['session_expiry']);

        // Supprimer les anciennes références à interface et utiliser directement le rôle
        await saveUser(user);

        // Configurer la session
        setSessionId(user.sessionId);

        debugPrint('Utilisateur créé et sauvegardé: ${user.toJson()}');
        debugPrint('Vérification des rôles: role=${user.role}');
        debugPrint('Rôle utilisateur: ${getUserRole()}');
      }

      // Si la clé 'amicale' existe, examiner son contenu
      if (apiResult['amicale'] != null) {
        debugPrint('Détails amicale:');

        // Passer directement les données d'amicale au repository
        // Le repository a été modifié pour gérer tous les formats possibles
        final amicaleRepository = AmicaleRepository(_apiService);
        await amicaleRepository.processAmicalesData(apiResult['amicale']);

        debugPrint('Amicales traitées et stockées via AmicaleRepository');
      }

      // Si la clé 'clients' existe, examiner son contenu
      if (apiResult['clients'] != null) {
        debugPrint('Détails clients:');
        List<dynamic> clientsList;

        if (apiResult['clients'] is List) {
          clientsList = apiResult['clients'] as List<dynamic>;
        } else if (apiResult['clients'] is Map &&
            apiResult['clients'].containsKey('data')) {
          clientsList = apiResult['clients']['data'] as List<dynamic>;
        } else {
          debugPrint('Format de données de clients non reconnu');
          clientsList = [];
        }

        // Si l'utilisateur a un rôle > 2, traiter les clients
        if (clientsList.isNotEmpty) {
          debugPrint('Traitement de ${clientsList.length} clients de type 1');

          // Utiliser le ClientRepository pour traiter les données des clients
          final clientRepository = ClientRepository(_apiService);
          await clientRepository.processClientsData(clientsList);

          debugPrint('Clients traités et stockés via ClientRepository');
        } else {
          debugPrint('Aucun client à traiter (rôle utilisateur <= 2)');
        }
      }

      // Étape 6: Traitement des opérations (50%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.50,
        stepDescription: 'Chargement des opérations',
      ));

      debugPrint('Traitement des données...');

      // Traitement des données des opérations, secteurs, passages et membres
      // Ces données devraient être présentes dans la réponse API
      if (apiResult.containsKey('operations')) {
        await _processOperations(apiResult['operations']);
        debugPrint('Nombre d\'opérations chargées: ${_operationBox.length}');
      }

      // Étape 7: Traitement des secteurs (65%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.65,
        stepDescription: 'Chargement des secteurs',
      ));

      if (apiResult.containsKey('sectors')) {
        await _processSectors(apiResult['sectors']);
        debugPrint('Nombre de secteurs chargés: ${_sectorBox.length}');
      }

      // Étape 8: Traitement des passages (75%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.75,
        stepDescription: 'Chargement des passages',
      ));

      if (apiResult.containsKey('passages')) {
        await _processPassages(apiResult['passages']);
        debugPrint('Nombre de passages chargés: ${_passageBox.length}');
      }

      // Étape 9: Traitement des membres (85%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.85,
        stepDescription: 'Chargement des membres',
      ));

      // Traitement des membres
      if (apiResult.containsKey('membres') ||
          apiResult.containsKey('members')) {
        final membresData = apiResult['membres'] ?? apiResult['members'];
        if (membresData != null) {
          await _processMembres(membresData);
          debugPrint('Nombre de membres chargés: ${_membreBox.length}');
        }
      }

      // Étape 10: Traitement des associations utilisateurs-secteurs (95%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.95,
        stepDescription: 'Finalisation du chargement',
      ));

      // Traitement des associations utilisateurs-secteurs
      if (apiResult.containsKey('users_sectors')) {
        await _processUserSectors(apiResult['users_sectors']);
        debugPrint(
            'Nombre d\'associations utilisateurs-secteurs chargées: ${_userSectorBox.length}');
      }

      // Vérification finale du remplissage des boîtes
      debugPrint('=== VÉRIFICATION DU REMPLISSAGE DES BOÎTES ===');
      debugPrint('Utilisateurs: ${_userBox.length}');
      debugPrint('Opérations: ${_operationBox.length}');
      debugPrint('Secteurs: ${_sectorBox.length}');
      debugPrint('Passages: ${_passageBox.length}');
      debugPrint('Membres: ${_membreBox.length}');

      // Afficher le nombre d'associations utilisateurs-secteurs avec plus de détails
      final userSectorCount = _userSectorBox.length;
      debugPrint('Associations utilisateurs-secteurs: $userSectorCount');

      // Si des associations existent, afficher quelques détails
      if (userSectorCount > 0) {
        debugPrint('--- Détails des associations utilisateurs-secteurs ---');
        int displayCount = 0;
        for (final userSector in _userSectorBox.values) {
          if (displayCount < 5) {
            // Limiter à 5 pour éviter de surcharger la console
            debugPrint(
                '  User ${userSector.id} (${userSector.firstName}) -> Secteur ${userSector.fkSector} (${userSector.name})');
            displayCount++;
          } else {
            debugPrint('  ... et ${userSectorCount - 5} autres associations');
            break;
          }
        }
      }

      // Étape 11: Vérification finale des données (95%)
      _updateLoadingState(_loadingState.copyWith(
        progress: 0.95,
        stepDescription: 'Vérification finale des données',
      ));

      // Vérifier que le nombre de passages dans la réponse API correspond au nombre dans la Hive Box
      int passagesCountInResponse = 0;
      if (apiResult.containsKey('passages')) {
        if (apiResult['passages'] is List) {
          passagesCountInResponse = (apiResult['passages'] as List).length;
        } else if (apiResult['passages'] is Map &&
            apiResult['passages'].containsKey('data')) {
          passagesCountInResponse =
              (apiResult['passages']['data'] as List).length;
        }
      }

      int passagesCountInBox = _passageBox.length;
      debugPrint(
          'Nombre de passages dans la réponse API: $passagesCountInResponse');
      debugPrint('Nombre de passages dans la Hive Box: $passagesCountInBox');

      // Si les nombres ne correspondent pas, attendre un peu et revérifier
      if (passagesCountInResponse > 0 &&
          passagesCountInBox < passagesCountInResponse) {
        debugPrint(
            'Attente supplémentaire pour finaliser le chargement des passages...');
        await Future.delayed(const Duration(seconds: 1));
        passagesCountInBox = _passageBox.length;
        debugPrint(
            'Après attente: Nombre de passages dans la Hive Box: $passagesCountInBox');
      }

      // Étape 12: Chargement terminé (100%)
      _updateLoadingState(LoadingState.completed.copyWith(
        progress: 1.0,
        message: 'Chargement terminé avec succès',
        stepDescription: 'Connexion réussie',
      ));

      debugPrint('==========================================');
      debugPrint('VÉRIFICATION FINALE DES DONNÉES:');
      debugPrint('Utilisateurs: ${_userBox.length}');
      debugPrint('Opérations: ${_operationBox.length}');
      debugPrint('Secteurs: ${_sectorBox.length}');
      debugPrint('Passages: ${_passageBox.length}');
      debugPrint('Membres: ${_membreBox.length}');
      debugPrint('==========================================');

      return true;
    } catch (e) {
      debugPrint('Erreur de connexion: $e');
      _updateLoadingState(LoadingState.error(e.toString()));
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
    }
  }

  // Méthode pour vérifier si une boîte est ouverte et l'ouvrir si nécessaire
  Future<void> _ensureBoxIsOpen(String boxName) async {
    try {
      if (!Hive.isBoxOpen(boxName)) {
        debugPrint('Ouverture de la boîte $boxName...');
        if (boxName == AppKeys.passagesBoxName) {
          await Hive.openBox<PassageModel>(boxName);
        } else if (boxName == AppKeys.operationsBoxName) {
          await Hive.openBox<OperationModel>(boxName);
        } else if (boxName == AppKeys.sectorsBoxName) {
          await Hive.openBox<SectorModel>(boxName);
        } else if (boxName == AppKeys.usersBoxName) {
          await Hive.openBox<UserModel>(boxName);
        } else if (boxName == AppKeys.membresBoxName) {
          await Hive.openBox<MembreModel>(boxName);
        } else if (boxName == AppKeys.settingsBoxName) {
          await Hive.openBox(boxName);
        } else if (boxName == AppKeys.chatConversationsBoxName) {
          await Hive.openBox<ConversationModel>(boxName);
        } else if (boxName == AppKeys.chatMessagesBoxName) {
          await Hive.openBox<MessageModel>(boxName);
        } else if (boxName == AppKeys.userSectorBoxName) {
          await Hive.openBox<UserSectorModel>(boxName);
        } else {
          await Hive.openBox(boxName);
        }
        // Boîte ouverte avec succès
      } else {
        // La boîte est déjà ouverte
      }
    } catch (e) {
      debugPrint('Erreur lors de l\'ouverture de la boîte $boxName: $e');
      throw Exception('Impossible d\'ouvrir la boîte $boxName: $e');
    }
  }

  // Méthode pour vider et recréer toutes les boîtes Hive sauf la boîte des utilisateurs
  Future<void> _clearAndRecreateBoxes() async {
    try {
      debugPrint('Début de la suppression complète des données Hive...');

      // Supprimer les références aux boîtes non définies dans AppKeys
      // pour éviter les erreurs de suppression de boîtes non référencées
      final nonDefinedBoxes = ['auth', 'locations', 'messages'];
      for (final boxName in nonDefinedBoxes) {
        try {
          if (Hive.isBoxOpen(boxName)) {
            debugPrint('Fermeture de la boîte non référencée: $boxName');
            await Hive.box(boxName).close();
          }

          // Supprimer la boîte du disque
          await Hive.deleteBoxFromDisk(boxName);
          debugPrint('Nettoyage: Box $boxName supprimée');
        } catch (e) {
          debugPrint(
              'Erreur lors de la suppression de la boîte non référencée $boxName: $e');
        }
      }

      // Sur le web, utiliser notre méthode sécurisée pour nettoyer les boîtes Hive
      if (kIsWeb) {
        await HiveWebFix.safeCleanHiveBoxes(
            excludeBoxes: [AppKeys.usersBoxName]);
      }
      // Sur iOS, nettoyer les fichiers Hive directement
      else if (Platform.isIOS) {
        await _cleanHiveFilesOnIOS();
      }
      // Sur Android, nettoyer les fichiers Hive directement
      else if (Platform.isAndroid) {
        await _cleanHiveFilesOnAndroid();
      }

      // Liste des noms de boîtes à supprimer
      final boxesToDelete = [
        AppKeys.passagesBoxName,
        AppKeys.operationsBoxName,
        AppKeys.sectorsBoxName,
        AppKeys.userSectorBoxName,
        AppKeys.chatConversationsBoxName,
        AppKeys.chatMessagesBoxName,
      ];

      // Vider chaque boîte sans la fermer
      for (final boxName in boxesToDelete) {
        try {
          debugPrint('Nettoyage de la boîte: $boxName');

          // Vérifier si la boîte est déjà ouverte
          if (Hive.isBoxOpen(boxName)) {
            // Vider la boîte sans la fermer
            debugPrint('Boîte $boxName déjà ouverte, vidage sans fermeture');
            if (boxName == AppKeys.passagesBoxName) {
              await _passageBox.clear();
            } else if (boxName == AppKeys.operationsBoxName) {
              await _operationBox.clear();
            } else if (boxName == AppKeys.sectorsBoxName) {
              await _sectorBox.clear();
            } else if (boxName == AppKeys.userSectorBoxName) {
              await _userSectorBox.clear();
            } else if (boxName == AppKeys.chatConversationsBoxName) {
              await _chatConversationBox.clear();
            } else if (boxName == AppKeys.chatMessagesBoxName) {
              await _chatMessageBox.clear();
            }
          } else {
            // Supprimer la boîte du disque si elle n'est pas ouverte
            debugPrint('Boîte $boxName non ouverte, suppression du disque');
            await Hive.deleteBoxFromDisk(boxName);
          }
        } catch (e) {
          debugPrint('Erreur lors du nettoyage de la boîte $boxName: $e');
          // Tenter de supprimer la boîte du disque en cas d'erreur
          try {
            await Hive.deleteBoxFromDisk(boxName);
          } catch (deleteError) {
            debugPrint(
                'Impossible de supprimer la boîte $boxName: $deleteError');
          }
        }
      }

      // Attendre un court instant pour s'assurer que les opérations de suppression sont terminées
      await Future.delayed(const Duration(milliseconds: 500));

      // Recréer les boîtes avec la méthode sécurisée
      debugPrint('Recréation des boîtes Hive...');

      // Utiliser notre méthode pour s'assurer que les boîtes sont ouvertes
      try {
        // Passages
        await _ensureBoxIsOpen(AppKeys.passagesBoxName);

        // Opérations
        await _ensureBoxIsOpen(AppKeys.operationsBoxName);

        // Secteurs
        await _ensureBoxIsOpen(AppKeys.sectorsBoxName);

        // Chat
        await _ensureBoxIsOpen(AppKeys.chatConversationsBoxName);
        await _ensureBoxIsOpen(AppKeys.chatMessagesBoxName);

        // Vérifier l'intégrité des boîtes après recréation
        await _verifyHiveBoxesIntegrity();
      } catch (e) {
        debugPrint('Erreur lors de la recréation des boîtes Hive: $e');
        // Tentative de récupération sur erreur
        if (kIsWeb) {
          debugPrint('Tentative de récupération sur le web...');
          await HiveWebFix.resetHiveCompletely();

          // Réessayer d'ouvrir les boîtes
          await _ensureBoxIsOpen(AppKeys.passagesBoxName);
          await _ensureBoxIsOpen(AppKeys.operationsBoxName);
          await _ensureBoxIsOpen(AppKeys.sectorsBoxName);
          await _ensureBoxIsOpen(AppKeys.chatConversationsBoxName);
          await _ensureBoxIsOpen(AppKeys.chatMessagesBoxName);
        }
      }
    } catch (e) {
      debugPrint('Erreur lors de la réinitialisation des boîtes Hive: $e');
    }
  }

  // Méthode pour vérifier l'intégrité des boîtes Hive après recréation
  Future<void> _verifyHiveBoxesIntegrity() async {
    try {
      debugPrint('Vérification de l\'intégrité des boîtes Hive...');

      // Liste des boîtes à vérifier avec leur type
      final boxesToCheck = [
        {'name': AppKeys.passagesBoxName, 'type': 'passage'},
        {'name': AppKeys.operationsBoxName, 'type': 'operation'},
        {'name': AppKeys.sectorsBoxName, 'type': 'sector'},
        {'name': AppKeys.userSectorBoxName, 'type': 'user_sector'},
        {'name': AppKeys.amicaleBoxName, 'type': 'amicale'},
        {'name': AppKeys.chatConversationsBoxName, 'type': 'conversation'},
        {'name': AppKeys.chatMessagesBoxName, 'type': 'message'},
      ];

      // Vérifier chaque boîte
      for (final boxInfo in boxesToCheck) {
        final boxName = boxInfo['name'] as String;
        final boxType = boxInfo['type'] as String;

        try {
          if (Hive.isBoxOpen(boxName)) {
            // Utiliser une approche spécifique au type pour éviter les erreurs de typage
            Box box;
            try {
              if (boxType == 'passage') {
                box = _passageBox;
              } else if (boxType == 'operation') {
                box = _operationBox;
              } else if (boxType == 'sector') {
                box = _sectorBox;
              } else if (boxType == 'user_sector') {
                box = _userSectorBox;
              } else if (boxType == 'conversation') {
                box = _chatConversationBox;
              } else if (boxType == 'message') {
                box = _chatMessageBox;
              } else {
                box = Hive.box(boxName);
              }

              final count = box.length;
              debugPrint('Boîte $boxName: $count éléments');

              // Si la boîte contient des éléments, c'est anormal après recréation
              if (count > 0) {
                debugPrint(
                    'ATTENTION: La boîte $boxName contient encore des données après recréation');
                // Essayer de vider la boîte une dernière fois
                await box.clear();
                debugPrint('Vidage forcé de la boîte $boxName effectué');
              }
            } catch (typeError) {
              debugPrint(
                  'Erreur de typage lors de la vérification de $boxName: $typeError');

              // Tentative alternative sans typage spécifique
              try {
                box = Hive.box(boxName);
                final count = box.length;
                debugPrint('Boîte $boxName (sans typage): $count éléments');

                if (count > 0) {
                  await box.clear();
                  debugPrint(
                      'Vidage forcé de la boîte $boxName (sans typage) effectué');
                }
              } catch (e2) {
                debugPrint(
                    'Impossible de vérifier la boîte $boxName même sans typage: $e2');
              }
            }
          } else {
            debugPrint(
                'Boîte $boxName non ouverte, impossible de vérifier l\'intégrité');
          }
        } catch (e) {
          debugPrint('Erreur lors de la vérification de la boîte $boxName: $e');
        }
      }

      debugPrint('Vérification d\'intégrité terminée');
    } catch (e) {
      debugPrint(
          'Erreur lors de la vérification d\'intégrité des boîtes Hive: $e');
    }
  }

  // Méthode spéciale pour nettoyer IndexedDB sur le web
  Future<void> _clearIndexedDB() async {
    if (kIsWeb) {
      try {
        debugPrint('Nettoyage complet d\'IndexedDB sur le web...');
        // Utiliser JavaScript pour nettoyer IndexedDB
        js.context.callMethod('eval', [
          '''
          var request = indexedDB.deleteDatabase("geosector_app");
          request.onsuccess = function() { console.log("IndexedDB nettoyé avec succès"); };
          request.onerror = function() { console.log("Erreur lors du nettoyage d\'IndexedDB"); };
          '''
        ]);
        await Future.delayed(const Duration(milliseconds: 500));
        debugPrint('Nettoyage d\'IndexedDB terminé');
      } catch (e) {
        debugPrint('Erreur lors du nettoyage d\'IndexedDB: $e');
      }
    }
  }

  // Méthode spéciale pour nettoyer les fichiers Hive sur iOS
  Future<void> _cleanHiveFilesOnIOS() async {
    if (!kIsWeb && Platform.isIOS) {
      try {
        debugPrint('Nettoyage des fichiers Hive sur iOS...');
        final appDir = await getApplicationDocumentsDirectory();
        final hiveDir = Directory('${appDir.path}/hive');

        if (await hiveDir.exists()) {
          debugPrint('Suppression du répertoire Hive: ${hiveDir.path}');
          // Exclure le dossier des utilisateurs pour conserver les informations de session
          final entries = await hiveDir.list().toList();
          for (var entry in entries) {
            final name = entry.path.split('/').last;
            // Ne pas supprimer la boîte des utilisateurs
            if (!name.contains(AppKeys.usersBoxName)) {
              debugPrint('Suppression de: ${entry.path}');
              if (entry is Directory) {
                await entry.delete(recursive: true);
              } else if (entry is File) {
                await entry.delete();
              }
            }
          }
          debugPrint('Nettoyage des fichiers Hive sur iOS terminé');
        } else {
          debugPrint('Répertoire Hive non trouvé');
        }
      } catch (e) {
        debugPrint('Erreur lors du nettoyage des fichiers Hive sur iOS: $e');
      }
    }
  }

  // Méthode spéciale pour nettoyer les fichiers Hive sur Android
  Future<void> _cleanHiveFilesOnAndroid() async {
    if (!kIsWeb && Platform.isAndroid) {
      try {
        debugPrint('Nettoyage des fichiers Hive sur Android...');
        final appDir = await getApplicationDocumentsDirectory();
        final hiveDir = Directory('${appDir.path}');

        if (await hiveDir.exists()) {
          debugPrint('Recherche des fichiers Hive dans: ${hiveDir.path}');
          // Sur Android, les fichiers Hive sont directement dans le répertoire de l'application
          final entries = await hiveDir.list().toList();
          int filesDeleted = 0;

          for (var entry in entries) {
            final name = entry.path.split('/').last;
            // Ne supprimer que les fichiers Hive, mais pas la boîte des utilisateurs
            if (name.endsWith('.hive') &&
                !name.contains(AppKeys.usersBoxName)) {
              debugPrint('Suppression du fichier Hive: ${entry.path}');
              if (entry is File) {
                await entry.delete();
                filesDeleted++;

                // Supprimer également les fichiers lock associés
                final lockFile = File('${entry.path}.lock');
                if (await lockFile.exists()) {
                  await lockFile.delete();
                  debugPrint('Suppression du fichier lock: ${lockFile.path}');
                }
              }
            }
          }

          debugPrint(
              'Nettoyage des fichiers Hive sur Android terminé. $filesDeleted fichiers supprimés.');
        } else {
          debugPrint('Répertoire d\'application non trouvé');
        }
      } catch (e) {
        debugPrint(
            'Erreur lors du nettoyage des fichiers Hive sur Android: $e');
      }
    }
  }

  /// Méthode de connexion avec affichage d'un overlay de chargement avec progression
  /// Cette méthode remplace AuthService.login et utilise le nouvel overlay avec barre de progression
  Future<bool> loginWithUI(
      BuildContext context, String username, String password,
      {required String type}) async {
    try {
      // Réinitialiser l'état de chargement
      _updateLoadingState(LoadingState.initial.copyWith(
        message: 'Connexion en cours...',
        stepDescription: 'Préparation',
      ));

      // Créer et afficher l'overlay de progression
      _progressOverlay = LoadingProgressOverlayUtils.show(
        context: context,
        message: 'Connexion en cours...',
        progress: 0.0,
        stepDescription: 'Préparation',
        blurAmount: 5.0,
      );

      // Écouter les changements d'état pour mettre à jour l'overlay
      final listener = () {
        if (_progressOverlay != null) {
          // Mettre à jour l'overlay avec les nouvelles valeurs
          LoadingProgressOverlayUtils.update(
            overlayEntry: _progressOverlay!,
            message: _loadingState.message,
            progress: _loadingState.progress,
            stepDescription: _loadingState.stepDescription,
          );
        }
      };

      // Ajouter l'écouteur
      addListener(listener);

      // Exécuter la connexion
      final result = await login(username, password, type: type);

      // Attendre un court instant pour que l'utilisateur voie que le chargement est terminé
      if (result) {
        await Future.delayed(const Duration(milliseconds: 500));
      } else {
        await Future.delayed(const Duration(seconds: 2));
      }

      // Supprimer l'overlay
      if (_progressOverlay != null) {
        _progressOverlay!.remove();
        _progressOverlay = null;
      }

      // Supprimer l'écouteur
      removeListener(listener);

      return result;
    } catch (e) {
      // En cas d'erreur, supprimer l'overlay et relancer l'erreur
      if (_progressOverlay != null) {
        _progressOverlay!.remove();
        _progressOverlay = null;
      }

      _updateLoadingState(LoadingState.error(e.toString()));
      return false;
    }
  }

  /// Méthode de déconnexion avec affichage d'un overlay de chargement
  /// et redirection vers la page de démarrage
  /// Cette méthode remplace AuthService.logout
  Future<bool> logoutWithUI(BuildContext context) async {
    final bool result = await LoadingOverlay.show(
      context: context,
      spinnerSize: 80.0, // Spinner plus grand
      strokeWidth: 6.0, // Trait plus épais
      future: logout(),
    );

    // Si la déconnexion a réussi, rediriger vers la page de démarrage
    if (result && context.mounted) {
      // Utiliser GoRouter pour naviguer vers la page de démarrage
      GoRouter.of(context).go('/');
    }

    return result;
  }

  // Logout complet (sans UI)
  Future<bool> logout() async {
    _isLoading = true;
    notifyListeners();

    try {
      debugPrint('Début du processus de déconnexion...');
      debugPrint('État isLoggedIn avant déconnexion: $isLoggedIn');

      // Récupérer l'utilisateur actuel avant de nettoyer les données
      final currentUser = getCurrentUser();
      if (currentUser == null) {
        debugPrint('Aucun utilisateur connecté, déconnexion terminée');
        // Nettoyage en profondeur même si aucun utilisateur n'est connecté
        await _deepCleanHiveBoxes();
        debugPrint('État isLoggedIn après nettoyage: $isLoggedIn');
        return true;
      }

      debugPrint('Déconnexion de l\'utilisateur: ${currentUser.email}');

      // Appeler l'API pour déconnecter la session
      if (currentUser.sessionId != null) {
        debugPrint('Déconnexion de la session API...');
        try {
          await logoutAPI();
        } catch (e) {
          debugPrint('Erreur lors de la déconnexion API, mais on continue: $e');
          // Continuer le processus de déconnexion même si l'API échoue
        }
      }

      // Effacer la session de l'utilisateur
      debugPrint('Mise à jour de l\'utilisateur pour effacer la session...');

      // Supprimer la session API
      setSessionId(null);

      // Réinitialiser le cache de l'utilisateur actuel
      _cachedCurrentUser = null;
      debugPrint('Cache utilisateur réinitialisé (_cachedCurrentUser = null)');

      // MODIFICATION IMPORTANTE: Nettoyage complet de toutes les boîtes Hive
      debugPrint('Nettoyage profond des données Hive après déconnexion...');
      await _deepCleanHiveBoxes();

      // Vérifier l'état après nettoyage
      debugPrint('État isLoggedIn après déconnexion: $isLoggedIn');
      debugPrint(
          'Valeur de currentUser après déconnexion: ${currentUser != null ? "non null" : "null"}');

      // Vérifier si des utilisateurs restent dans la boîte
      if (Hive.isBoxOpen(AppKeys.usersBoxName)) {
        final remainingUsers = _userBox.values.toList();
        debugPrint(
            'Nombre d\'utilisateurs restants dans la boîte: ${remainingUsers.length}');
      }

      // Réinitialiser l'état de HiveResetStateService
      hiveResetStateService.reset();
      debugPrint('État de HiveResetStateService réinitialisé');

      debugPrint('Déconnexion terminée avec succès');

      notifyListeners();
      return true;
    } catch (e) {
      debugPrint('Erreur de déconnexion: $e');
      return false;
    } finally {
      _isLoading = false;
      notifyListeners();
      // Vérification finale
      debugPrint('État final isLoggedIn: $isLoggedIn');
    }
  }

  // Méthode pour nettoyer en profondeur toutes les boîtes Hive et réinitialiser l'application
  Future<void> _deepCleanHiveBoxes() async {
    try {
      debugPrint('Début du nettoyage profond des boîtes Hive...');

      // Sauvegarder le username et le rôle du dernier utilisateur connecté pour le pré-remplissage
      String? lastUsername;
      int? lastRole;
      UserModel? lastUser;
      if (Hive.isBoxOpen(AppKeys.usersBoxName) && _userBox.isNotEmpty) {
        try {
          // Récupérer l'utilisateur actuel ou le dernier utilisateur connecté
          lastUser = getCurrentUser() ?? _userBox.values.first;
          if (lastUser != null) {
            lastUsername = lastUser.username;

            // Convertir le rôle en int si nécessaire
            if (lastUser.role is String) {
              lastRole = int.tryParse(lastUser.role as String) ?? 0;
            } else {
              lastRole = lastUser.role as int;
            }

            debugPrint(
                'Username sauvegardé pour pré-remplissage: $lastUsername');
            debugPrint('Rôle sauvegardé pour pré-remplissage: $lastRole');
          }
        } catch (e) {
          debugPrint('Erreur lors de la sauvegarde du username et du rôle: $e');
        }
      }

      // 1. Vider toutes les boîtes sans les fermer
      debugPrint('Vidage des boîtes Hive...');
      if (Hive.isBoxOpen(AppKeys.usersBoxName)) {
        try {
          await _userBox.clear();
          debugPrint('Boîte users vidée');

          // Si nous avons un username sauvegardé, créer un utilisateur minimal pour le pré-remplissage
          if (lastUsername != null && lastUsername.isNotEmpty) {
            final minimalUser = UserModel(
              id: lastUser?.id ?? DateTime.now().millisecondsSinceEpoch,
              email: lastUser?.email ?? '',
              username: lastUsername,
              role: lastRole ??
                  0, // Conserver le rôle pour la vérification dans la page de login
              createdAt: DateTime.now(),
              lastSyncedAt: DateTime.now(),
              isActive: false,
              isSynced: false,
            );
            await _userBox.put(minimalUser.id, minimalUser);
            debugPrint(
                'Utilisateur minimal créé pour pré-remplissage du username avec rôle: $lastRole');
          }
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte users: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.operationsBoxName)) {
        try {
          await _operationBox.clear();
          debugPrint('Boîte operations vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte operations: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.sectorsBoxName)) {
        try {
          await _sectorBox.clear();
          debugPrint('Boîte sectors vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte sectors: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.passagesBoxName)) {
        try {
          await _passageBox.clear();
          debugPrint('Boîte passages vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte passages: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.settingsBoxName)) {
        try {
          await _settingsBox.clear();
          debugPrint('Boîte settings vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte settings: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.membresBoxName)) {
        try {
          await _membreBox.clear();
          debugPrint('Boîte membres vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte membres: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.chatConversationsBoxName)) {
        try {
          await _chatConversationBox.clear();
          debugPrint('Boîte chat_conversations vidée');
        } catch (e) {
          debugPrint(
              'Erreur lors du vidage de la boîte chat_conversations: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.chatMessagesBoxName)) {
        try {
          await _chatMessageBox.clear();
          debugPrint('Boîte chat_messages vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte chat_messages: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.userSectorBoxName)) {
        try {
          await _userSectorBox.clear();
          debugPrint('Boîte user_sector vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte user_sector: $e');
        }
      }

      if (Hive.isBoxOpen(AppKeys.amicaleBoxName)) {
        try {
          await _amicaleBox.clear();
          debugPrint('Boîte amicale vidée');
        } catch (e) {
          debugPrint('Erreur lors du vidage de la boîte amicales: $e');
        }
      }

      // 2. Nettoyage spécifique à la plateforme
      if (kIsWeb) {
        await _clearIndexedDB();
      } else if (!kIsWeb && Platform.isIOS) {
        await _cleanHiveFilesOnIOS();
      } else if (!kIsWeb && Platform.isAndroid) {
        await _cleanHiveFilesOnAndroid();
      }

      // 3. Attendre que toutes les opérations de nettoyage soient terminées
      debugPrint('Attente après nettoyage...');
      await Future.delayed(const Duration(milliseconds: 800));

      // 4. Réinitialiser l'API Service
      _apiService.setSessionId(null);

      // 5. Approche plus sûre : fermer, supprimer et rouvrir la boîte des utilisateurs
      debugPrint('Approche sécurisée pour la boîte users...');

      try {
        // Vérifier si la boîte est ouverte avant de tenter de la fermer
        if (Hive.isBoxOpen(AppKeys.usersBoxName)) {
          debugPrint('Fermeture de la boîte users...');
          try {
            await Hive.box<UserModel>(AppKeys.usersBoxName).close();
            debugPrint('Boîte users fermée avec succès');
          } catch (e) {
            debugPrint('Erreur lors de la fermeture de la boîte users: $e');
            // Ne pas continuer avec la suppression si la fermeture a échoué
            throw e;
          }

          // Attendre un peu pour s'assurer que la fermeture est terminée
          await Future.delayed(const Duration(milliseconds: 300));

          // Supprimer la boîte du disque seulement si la fermeture a réussi
          debugPrint('Suppression de la boîte users du disque...');
          try {
            await Hive.deleteBoxFromDisk(AppKeys.usersBoxName);
            debugPrint('Boîte users supprimée du disque avec succès');
          } catch (e) {
            debugPrint('Erreur lors de la suppression de la boîte users: $e');
            // Ne pas continuer avec la réouverture si la suppression a échoué
            throw e;
          }
        } else {
          debugPrint(
              'La boîte users est déjà fermée, tentative de suppression directe...');
          try {
            await Hive.deleteBoxFromDisk(AppKeys.usersBoxName);
            debugPrint('Boîte users supprimée du disque avec succès');
          } catch (e) {
            debugPrint(
                'Erreur lors de la suppression directe de la boîte users: $e');
          }
        }
      } catch (e) {
        debugPrint(
            'Erreur lors du processus de nettoyage de la boîte users: $e');
        // Continuer malgré l'erreur, mais ne pas tenter de réouvrir la boîte
        return;
      }

      // Attendre un peu pour s'assurer que la suppression est terminée
      await Future.delayed(const Duration(milliseconds: 500));

      // Rouvrir la boîte (elle sera vide)
      debugPrint('Réouverture de la boîte users (vide)...');
      await Hive.openBox<UserModel>(AppKeys.usersBoxName);

      // Vérifier que la boîte est bien vide
      final checkUsers = _userBox.values.toList();
      debugPrint(
          'Après approche radicale: ${checkUsers.length} utilisateurs restants');

      // Forcer la réinitialisation du cache
      _cachedCurrentUser = null;
      debugPrint('Cache utilisateur forcé à null');

      debugPrint('Nettoyage profond des boîtes Hive terminé');
    } catch (e) {
      debugPrint('Erreur lors du nettoyage profond des boîtes Hive: $e');
    }
  }

  // Obtenir tous les utilisateurs locaux
  List<UserModel> getAllUsers() {
    return _userBox.values.toList();
  }

  // Obtenir un utilisateur par son ID
  UserModel? getUserById(int id) {
    return _userBox.get(id);
  }

  // Obtenir un utilisateur par son email
  UserModel? getUserByEmail(String email) {
    try {
      return _userBox.values.firstWhere(
        (user) => user.email == email,
      );
    } catch (e) {
      return null; // Utilisateur non trouvé
    }
  }

  // Créer ou mettre à jour un utilisateur localement
  Future<UserModel> saveUser(UserModel user) async {
    await _userBox.put(user.id, user);
    notifyListeners(); // Notifier les changements pour mettre à jour l'UI
    return user;
  }

  // Supprimer un utilisateur localement
  Future<void> deleteUser(String id) async {
    await _userBox.delete(id);
  }

  // Créer un nouvel utilisateur localement et tenter de le synchroniser
  Future<UserModel> createUser({
    required String email,
    required String name,
    required int role,
  }) async {
    // Générer un ID numérique temporaire (timestamp)
    final int tempId = DateTime.now().millisecondsSinceEpoch;
    final now = DateTime.now();

    final user = UserModel(
      id: tempId,
      email: email,
      name: name,
      role: role,
      createdAt: now,
      lastSyncedAt: now,
      isSynced: false,
    );

    await _userBox.put(user.id, user);

    // Tenter de synchroniser si possible
    await syncUser(user);

    return user;
  }

  // Synchroniser un utilisateur spécifique avec le serveur
  Future<UserModel> syncUser(UserModel user) async {
    try {
      final hasConnection = await _apiService.hasInternetConnection();

      if (!hasConnection) {
        return user;
      }

      UserModel syncedUser;

      if (!user.isSynced) {
        // Si l'utilisateur n'est pas encore synchronisé, le créer sur le serveur
        syncedUser = await _apiService.createUser(user);
      } else {
        // Sinon, mettre à jour les informations
        syncedUser = await _apiService.updateUser(user);
      }

      // Mettre à jour l'utilisateur local avec les informations du serveur
      final updatedUser = syncedUser.copyWith(
        isSynced: true,
        lastSyncedAt: DateTime.now(),
      );

      await _userBox.put(updatedUser.id, updatedUser);
      return updatedUser;
    } catch (e) {
      // En cas d'erreur, garder l'utilisateur local tel quel
      return user;
    }
  }

  // Synchroniser tous les utilisateurs non synchronisés
  Future<void> syncAllUsers() async {
    try {
      final hasConnection = await _apiService.hasInternetConnection();

      if (!hasConnection) {
        return;
      }

      final unsyncedUsers =
          _userBox.values.where((user) => !user.isSynced).toList();

      if (unsyncedUsers.isEmpty) {
        return;
      }

      // Synchroniser en batch
      final result = await _apiService.syncData(users: unsyncedUsers);

      // Mettre à jour les utilisateurs locaux
      if (result['users'] != null) {
        for (final userData in result['users']) {
          final syncedUser = UserModel.fromJson(userData);
          await _userBox.put(
            syncedUser.id,
            syncedUser.copyWith(
              isSynced: true,
              lastSyncedAt: DateTime.now(),
            ),
          );
        }
      }
    } catch (e) {
      // Gérer les erreurs de synchronisation
      print('Erreur de synchronisation des utilisateurs: $e');
    }
  }

  // Rafraîchir les données depuis le serveur
  Future<void> refreshFromServer() async {
    try {
      final hasConnection = await _apiService.hasInternetConnection();

      if (!hasConnection) {
        return;
      }

      // Récupérer tous les utilisateurs du serveur
      final serverUsers = await _apiService.getUsers();

      // Mettre à jour la base locale
      for (final serverUser in serverUsers) {
        final updatedUser = serverUser.copyWith(
          isSynced: true,
          lastSyncedAt: DateTime.now(),
        );
        await _userBox.put(updatedUser.id, updatedUser);
      }
    } catch (e) {
      // Gérer les erreurs
      print('Erreur lors du rafraîchissement des données: $e');
    }
  }

  // Synchroniser les données utilisateur
  Future<void> syncUserData() async {
    if (_syncService != null && currentUser != null) {
      await _syncService!.syncUserData(currentUser!.id);
    }
  }

  // Récupérer la dernière opération active (avec isActive == true)
  OperationModel? getCurrentOperation() {
    try {
      // Récupérer toutes les opérations
      final operations = _operationBox.values.toList();

      // Filtrer pour ne garder que les opérations actives
      final activeOperations = operations.where((op) => op.isActive).toList();

      // Si aucune opération active n'est trouvée, retourner null
      if (activeOperations.isEmpty) {
        return operations.isNotEmpty ? operations.last : null;
      }

      // Retourner la dernière opération active
      return activeOperations.last;
    } catch (e) {
      debugPrint('Erreur lors de la récupération de l\'opération actuelle: $e');
      return null;
    }
  }

  // Récupérer tous les secteurs de l'utilisateur
  List<SectorModel> getUserSectors() {
    try {
      return _sectorBox.values.toList();
    } catch (e) {
      debugPrint('Erreur lors de la récupération des secteurs: $e');
      return [];
    }
  }

  // Récupérer un secteur par son ID
  SectorModel? getSectorById(int id) {
    try {
      return _sectorBox.get(id);
    } catch (e) {
      debugPrint('Erreur lors de la récupération du secteur: $e');
      return null;
    }
  }

  // Récupérer toutes les amicales
  List<AmicaleModel> getAllAmicales() {
    try {
      _ensureBoxIsOpen(AppKeys.amicaleBoxName);
      return _amicaleBox.values.toList();
    } catch (e) {
      debugPrint('Erreur lors de la récupération des amicales: $e');
      return [];
    }
  }

  // Récupérer tous les clients (entités de type 1)
  List<AmicaleModel> getAllClients() {
    try {
      _ensureBoxIsOpen(AppKeys.amicaleBoxName);
      return _amicaleBox.values
          .where((amicale) => amicale.fkType == 1)
          .toList();
    } catch (e) {
      debugPrint('Erreur lors de la récupération des clients: $e');
      return [];
    }
  }

  // Récupérer une amicale par son ID
  AmicaleModel? getAmicaleById(int id) {
    try {
      _ensureBoxIsOpen(AppKeys.amicaleBoxName);
      return _amicaleBox.get(id);
    } catch (e) {
      debugPrint('Erreur lors de la récupération de l\'amicale: $e');
      return null;
    }
  }

  // Récupérer l'amicale de l'utilisateur connecté
  AmicaleModel? getCurrentUserAmicale() {
    final user = getCurrentUser();
    if (user == null || user.fkEntite == null) {
      return null;
    }

    return getAmicaleById(user.fkEntite!);
  }

  // Créer ou mettre à jour une amicale localement
  Future<AmicaleModel> saveAmicale(AmicaleModel amicale) async {
    _ensureBoxIsOpen(AppKeys.amicaleBoxName);
    await _amicaleBox.put(amicale.id, amicale);
    notifyListeners(); // Notifier les changements pour mettre à jour l'UI
    return amicale;
  }

  // Méthode pour traiter les données des opérations reçues de l'API
  Future<void> _processOperations(dynamic operationsData) async {
    try {
      debugPrint('Traitement des données des opérations...');

      // Vérifier que les données sont au bon format
      if (operationsData == null) {
        debugPrint('Aucune donnée d\'opération à traiter');
        return;
      }

      List<dynamic> operationsList;
      if (operationsData is List) {
        operationsList = operationsData;
      } else if (operationsData is Map && operationsData.containsKey('data')) {
        operationsList = operationsData['data'] as List<dynamic>;
      } else {
        debugPrint('Format de données d\'opérations non reconnu');
        return;
      }

      // Vider la boîte avant d'ajouter les nouvelles données
      await _operationBox.clear();

      // Traiter chaque opération
      int count = 0;
      for (final operationData in operationsList) {
        try {
          final operation = OperationModel.fromJson(operationData);
          await _operationBox.put(operation.id, operation);
          count++;
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'une opération: $e');
        }
      }

      debugPrint('$count opérations traitées et stockées');
    } catch (e) {
      debugPrint('Erreur lors du traitement des opérations: $e');
    }
  }

  // Méthode pour traiter les données des secteurs reçues de l'API
  Future<void> _processSectors(dynamic sectorsData) async {
    try {
      debugPrint('Traitement des données des secteurs...');

      // Vérifier que les données sont au bon format
      if (sectorsData == null) {
        debugPrint('Aucune donnée de secteur à traiter');
        return;
      }

      List<dynamic> sectorsList;
      if (sectorsData is List) {
        sectorsList = sectorsData;
      } else if (sectorsData is Map && sectorsData.containsKey('data')) {
        sectorsList = sectorsData['data'] as List<dynamic>;
      } else {
        debugPrint('Format de données de secteurs non reconnu');
        return;
      }

      // Vider la boîte avant d'ajouter les nouvelles données
      await _sectorBox.clear();

      // Traiter chaque secteur
      int count = 0;
      for (final sectorData in sectorsList) {
        try {
          final sector = SectorModel.fromJson(sectorData);
          await _sectorBox.put(sector.id, sector);
          count++;
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'un secteur: $e');
        }
      }

      debugPrint('$count secteurs traités et stockés');
    } catch (e) {
      debugPrint('Erreur lors du traitement des secteurs: $e');
    }
  }

  // Méthode pour traiter les données des passages reçues de l'API
  Future<void> _processPassages(dynamic passagesData) async {
    try {
      debugPrint('Traitement des données des passages...');

      // Vérifier que les données sont au bon format
      if (passagesData == null) {
        debugPrint('Aucune donnée de passage à traiter');
        return;
      }

      List<dynamic> passagesList;
      if (passagesData is List) {
        passagesList = passagesData;
      } else if (passagesData is Map && passagesData.containsKey('data')) {
        passagesList = passagesData['data'] as List<dynamic>;
      } else {
        debugPrint('Format de données de passages non reconnu');
        return;
      }

      // Vider la boîte avant d'ajouter les nouvelles données
      await _passageBox.clear();

      // Traiter chaque passage
      int count = 0;
      for (final passageData in passagesList) {
        try {
          final passage = PassageModel.fromJson(passageData);
          await _passageBox.put(passage.id, passage);
          count++;
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'un passage: $e');
        }
      }

      debugPrint('$count passages traités et stockés');
    } catch (e) {
      debugPrint('Erreur lors du traitement des passages: $e');
    }
  }

  // Méthode pour traiter les données des membres reçues de l'API
  Future<void> _processMembres(dynamic membresData) async {
    try {
      debugPrint('Traitement des données des membres...');

      // Vérifier que les données sont au bon format
      if (membresData == null) {
        debugPrint('Aucune donnée de membre à traiter');
        return;
      }

      List<dynamic> membresList;
      if (membresData is List) {
        membresList = membresData;
      } else if (membresData is Map && membresData.containsKey('data')) {
        membresList = membresData['data'] as List<dynamic>;
      } else {
        debugPrint('Format de données de membres non reconnu');
        return;
      }

      // Vider la boîte avant d'ajouter les nouvelles données
      await _membreBox.clear();

      // Traiter chaque membre
      int count = 0;
      for (final membreData in membresList) {
        try {
          final membre = MembreModel.fromJson(membreData);
          await _membreBox.put(membre.id, membre);
          count++;
        } catch (e) {
          debugPrint('Erreur lors du traitement d\'un membre: $e');
        }
      }

      debugPrint('$count membres traités et stockés');
    } catch (e) {
      debugPrint('Erreur lors du traitement des membres: $e');
    }
  }

  // Méthode pour traiter les données des associations utilisateurs-secteurs reçues de l'API
  Future<void> _processUserSectors(dynamic userSectorsData) async {
    try {
      debugPrint(
          'Traitement des données des associations utilisateurs-secteurs...');

      // Vérifier que les données sont au bon format
      if (userSectorsData == null) {
        debugPrint(
            'Aucune donnée d\'association utilisateur-secteur à traiter');
        return;
      }

      List<dynamic> userSectorsList;
      if (userSectorsData is List) {
        userSectorsList = userSectorsData;
      } else if (userSectorsData is Map &&
          userSectorsData.containsKey('data')) {
        userSectorsList = userSectorsData['data'] as List<dynamic>;
      } else {
        debugPrint(
            'Format de données d\'associations utilisateurs-secteurs non reconnu');
        return;
      }

      // Vider la boîte avant d'ajouter les nouvelles données
      await _userSectorBox.clear();

      // Traiter chaque association utilisateur-secteur
      int count = 0;
      for (final userSectorData in userSectorsList) {
        try {
          final userSector = UserSectorModel.fromJson(userSectorData);
          await _userSectorBox.put(
              '${userSector.id}_${userSector.fkSector}', userSector);
          count++;
        } catch (e) {
          debugPrint(
              'Erreur lors du traitement d\'une association utilisateur-secteur: $e');
        }
      }

      debugPrint(
          '$count associations utilisateurs-secteurs traitées et stockées');
    } catch (e) {
      debugPrint(
          'Erreur lors du traitement des associations utilisateurs-secteurs: $e');
    }
  }

  // Méthode pour traiter les données utilisateur reçues de l'API
  UserModel _processUserData(
      Map<String, dynamic> userData, String? sessionId, String? sessionExpiry) {
    debugPrint('Traitement des données utilisateur: ${userData.toString()}');

    // Convertir l'ID en int, qu'il soit déjà int ou string
    final dynamic rawId = userData['id'];
    final int id = rawId is String ? int.parse(rawId) : rawId as int;

    // Convertir le rôle en int, qu'il soit déjà int ou string
    final dynamic rawRole = userData['fk_role'];
    int role;
    if (rawRole is String) {
      role = int.tryParse(rawRole) ?? 1;
    } else if (rawRole is int) {
      role = rawRole;
    } else {
      // Valeur par défaut si le rôle n'est pas valide
      role = 1;
    }

    // Convertir fk_entite en int si présent
    final dynamic rawFkEntite = userData['fk_entite'];
    final int? fkEntite = rawFkEntite != null
        ? (rawFkEntite is String ? int.parse(rawFkEntite) : rawFkEntite as int)
        : null;

    // Convertir fk_titre en int si présent
    final dynamic rawFkTitre = userData['fk_titre'];
    final int? fkTitre = rawFkTitre != null
        ? (rawFkTitre is String ? int.parse(rawFkTitre) : rawFkTitre as int)
        : null;

    // Traiter les dates si présentes
    DateTime? dateNaissance;
    if (userData['date_naissance'] != null &&
        userData['date_naissance'] != '') {
      try {
        dateNaissance = DateTime.parse(userData['date_naissance']);
      } catch (e) {
        dateNaissance = null;
      }
    }

    DateTime? dateEmbauche;
    if (userData['date_embauche'] != null && userData['date_embauche'] != '') {
      try {
        dateEmbauche = DateTime.parse(userData['date_embauche']);
      } catch (e) {
        dateEmbauche = null;
      }
    }

    debugPrint('Données traitées - id: $id, role: $role, fkEntite: $fkEntite');

    // Créer un utilisateur avec toutes les données disponibles
    return UserModel(
      id: id,
      email: userData['email'] ?? '',
      name: userData['name'],
      username: userData['username'],
      firstName: userData['first_name'],
      role: role,
      createdAt: DateTime.now(), // Date actuelle comme fallback
      lastSyncedAt: DateTime.now(),
      isActive: true,
      isSynced: true,
      sessionId: sessionId,
      sessionExpiry:
          sessionExpiry != null ? DateTime.parse(sessionExpiry) : null,
      sectName: userData['sect_name'],
      fkEntite: fkEntite,
      fkTitre: fkTitre,
      phone: userData['phone'],
      mobile: userData['mobile'],
      dateNaissance: dateNaissance,
      dateEmbauche: dateEmbauche,
    );
  }
}
