# Guide de Gestion des Boîtes Hive dans GeoSector

Ce document explique comment les boîtes Hive sont gérées dans l'application GeoSector, particulièrement pendant les processus de connexion et déconnexion.

## Table des matières

1. [Introduction](#introduction)
2. [Boîtes Hive utilisées](#boîtes-hive-utilisées)
3. [Initialisation des boîtes Hive](#initialisation-des-boîtes-hive)
4. [Services et repositories impliqués](#services-et-repositories-impliqués)
5. [Processus de connexion (login)](#processus-de-connexion-login)
6. [Processus de déconnexion (logout)](#processus-de-déconnexion-logout)
7. [Problèmes connus et solutions](#problèmes-connus-et-solutions)
8. [Bonnes pratiques](#bonnes-pratiques)

## Introduction

Hive est une base de données NoSQL légère et rapide utilisée dans GeoSector pour stocker les données localement. Les données sont organisées en "boîtes" (boxes) qui peuvent être typées pour stocker des modèles spécifiques.

Dans cette application, Hive est utilisé pour :

- Stocker les données utilisateur et maintenir les sessions
- Conserver les données des opérations, secteurs et passages
- Permettre l'utilisation de l'application en mode hors ligne

## Boîtes Hive utilisées

Les boîtes Hive sont définies dans `lib/core/constants/app_keys.dart` :

```dart
// Noms des boîtes Hive
static const String usersBoxName = 'users';
static const String operationsBoxName = 'operations';
static const String sectorsBoxName = 'sectors';
static const String passagesBoxName = 'passages';
static const String settingsBoxName = 'settings';
```

Chaque boîte stocke un type spécifique de données :

- **users** : Stocke les informations des utilisateurs (`UserModel`)
- **operations** : Stocke les opérations (`OperationModel`)
- **sectors** : Stocke les secteurs (`SectorModel`)
- **passages** : Stocke les passages (`PassageModel`)
- **settings** : Stocke les préférences utilisateur (non typée)

## Initialisation des boîtes Hive

Actuellement, les boîtes Hive sont initialisées dès le démarrage de l'application dans `main.dart` :

```dart
// Initialiser Hive
await Hive.initFlutter();

// Enregistrer les adaptateurs Hive
Hive.registerAdapter(UserModelAdapter());
Hive.registerAdapter(OperationModelAdapter());
Hive.registerAdapter(SectorModelAdapter());
Hive.registerAdapter(PassageModelAdapter());

// Ouvrir les boîtes Hive
await Hive.openBox<UserModel>(AppKeys.userBoxName);
await Hive.openBox<OperationModel>(AppKeys.operationsBoxName);
await Hive.openBox<SectorModel>(AppKeys.sectorsBoxName);
await Hive.openBox<PassageModel>(AppKeys.passagesBoxName);
await Hive.openBox(AppKeys.settingsBoxName);
```

### Problème d'initialisation précoce

Cette approche ouvre toutes les boîtes Hive dès le démarrage de l'application, même sur les pages publiques comme `LandingPage` où elles ne sont pas nécessaires. Cela explique pourquoi vous voyez les messages suivants dans la console :

```
Got object store box in database users.
Got object store box in database operations.
Got object store box in database sectors.
Got object store box in database passages.
Got object store box in database settings.
```

### Solution recommandée

Pour optimiser l'initialisation des boîtes Hive, il est recommandé de :

1. N'initialiser que la boîte `users` au démarrage (pour vérifier si un utilisateur est déjà connecté)
2. Initialiser les autres boîtes uniquement après une connexion réussie

Modification suggérée pour `main.dart` :

```dart
// Initialiser Hive
await Hive.initFlutter();

// Enregistrer les adaptateurs Hive
Hive.registerAdapter(UserModelAdapter());
Hive.registerAdapter(OperationModelAdapter());
Hive.registerAdapter(SectorModelAdapter());
Hive.registerAdapter(PassageModelAdapter());

// N'ouvrir que la boîte des utilisateurs au démarrage
await Hive.openBox<UserModel>(AppKeys.userBoxName);
await Hive.openBox(AppKeys.settingsBoxName); // Préférences générales

// Les autres boîtes seront ouvertes après connexion dans UserRepository.login()
```

## Services et repositories impliqués

### UserRepository

Le `UserRepository` est le principal gestionnaire des boîtes Hive et de l'authentification. Il est responsable de :

- L'initialisation des boîtes au démarrage de l'application
- La gestion des boîtes pendant les processus de connexion et déconnexion
- Le nettoyage et la recréation des boîtes lorsque nécessaire
- La gestion complète de l'authentification (connexion et déconnexion)
- L'affichage des overlays de chargement pendant les opérations d'authentification
- La redirection vers les pages appropriées après connexion/déconnexion

> **Note importante** : Auparavant, l'application utilisait un service séparé `AuthService` pour gérer l'authentification. Cette classe a été supprimée et ses fonctionnalités ont été intégrées directement dans `UserRepository` pour simplifier l'architecture et éviter les problèmes de synchronisation entre les deux classes.

### Autres repositories spécialisés

- **OperationRepository** : Gère la boîte `operations`
- **SectorRepository** : Gère la boîte `sectors`
- **PassageRepository** : Gère la boîte `passages`

Ces repositories sont injectés dans le `UserRepository` pour traiter les données spécifiques à chaque modèle.

## Processus de connexion (login)

Le processus de connexion dans `UserRepository.login()` suit ces étapes :

1. **Nettoyage initial** :

   - Suppression des boîtes non référencées (`auth`, `locations`, `messages`)
   - Nettoyage adapté à la plateforme (Web, iOS, Android)

2. **Préparation des boîtes** :

   - Appel à `_clearAndRecreateBoxes()` pour vider et recréer les boîtes sans les fermer
   - Utilisation de `_ensureBoxIsOpen()` pour garantir que les boîtes sont ouvertes

3. **Appel API et traitement des données** :

   - Connexion via l'API
   - Vérification que toutes les boîtes sont ouvertes avant le traitement
   - Traitement des données reçues (opérations, secteurs, passages)

4. **Gestion des erreurs** :
   - Tentatives de récupération en cas d'erreur
   - Réouverture des boîtes si nécessaire

### Code clé pour la connexion

```dart
// S'assurer que les boîtes sont ouvertes
await _ensureBoxIsOpen(AppKeys.operationsBoxName);
await _ensureBoxIsOpen(AppKeys.sectorsBoxName);
await _ensureBoxIsOpen(AppKeys.passagesBoxName);

// Traiter les données
await _processOperations(operationsData);
await _processSectors(sectorsData);
await _processPassages(passagesData);
```

## Processus de déconnexion (logout)

Le processus de déconnexion dans `UserRepository.logout()` suit ces étapes :

1. **Préparation** :

   - Récupération de l'utilisateur actuel avant nettoyage
   - Déconnexion de la session API
   - Réinitialisation du cache de l'utilisateur actuel

2. **Nettoyage des données** :
   - Appel à `_deepCleanHiveBoxes()` pour un nettoyage complet des boîtes Hive

### Méthode \_deepCleanHiveBoxes

La méthode `_deepCleanHiveBoxes()` est cruciale pour le processus de déconnexion et suit ces étapes :

1. **Vidage des boîtes** :

   - Vidage de toutes les boîtes Hive ouvertes sans les fermer
   - Gestion des erreurs pour chaque boîte avec typage spécifique

2. **Nettoyage spécifique à la plateforme** :

   - Nettoyage adapté selon la plateforme (Web, iOS, Android)
   - Utilisation de méthodes spécifiques comme `_clearIndexedDB()` pour le web

3. **Réinitialisation** :
   - Réinitialisation de l'API Service

### Code clé pour la déconnexion

```dart
// Méthode logout
Future<bool> logout() async {
  try {
    // Récupérer l'utilisateur actuel avant de nettoyer les données
    final currentUser = getCurrentUser();

    // Déconnecter la session API
    if (currentUser?.sessionId != null) {
      await logoutAPI();
    }

    // Supprimer la session API
    setSessionId(null);

    // Réinitialiser le cache de l'utilisateur actuel
    _cachedCurrentUser = null;

    // Nettoyage complet des boîtes Hive
    await _deepCleanHiveBoxes();

    return true;
  } catch (e) {
    return false;
  }
}

// Méthode de nettoyage des boîtes Hive
Future<void> _deepCleanHiveBoxes() async {
  try {
    // 1. Vider toutes les boîtes sans les fermer
    if (Hive.isBoxOpen(AppKeys.userBoxName)) {
      await Hive.box<UserModel>(AppKeys.userBoxName).clear();
    }

    if (Hive.isBoxOpen(AppKeys.operationsBoxName)) {
      await Hive.box<OperationModel>(AppKeys.operationsBoxName).clear();
    }

    if (Hive.isBoxOpen(AppKeys.sectorsBoxName)) {
      await Hive.box<SectorModel>(AppKeys.sectorsBoxName).clear();
    }

    // Vider les autres boîtes...

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

    // 3. Réinitialiser l'API Service
    _apiService.setSessionId(null);
  } catch (e) {
    debugPrint('Erreur lors du nettoyage des boîtes Hive: $e');
  }
}
```

## Problèmes connus et solutions

### 1. Initialisation précoce des boîtes Hive

**Problème** : Toutes les boîtes Hive sont ouvertes dès le démarrage de l'application, même sur les pages publiques où elles ne sont pas nécessaires.

**Solution** : Modifier `main.dart` pour n'ouvrir que les boîtes essentielles au démarrage (users et settings) et initialiser les autres boîtes uniquement après connexion.

### 2. Erreur "Box has already been closed"

**Problème** : Des erreurs se produisent lorsqu'on tente d'accéder à une boîte qui a été fermée prématurément.

**Solution** :

- Utiliser la méthode `_ensureBoxIsOpen()` avant d'accéder à une boîte
- Éviter de fermer les boîtes qui pourraient être utilisées plus tard
- Préférer `box.clear()` à `box.close()` pour vider les données sans fermer la boîte

### 3. Persistance indésirable des données entre sessions

**Problème** : Les données peuvent persister entre les sessions utilisateur, créant des conflits ou des fuites de données.

**Solution** : Utiliser `_clearAndRecreateBoxes()` lors de la déconnexion pour vider correctement toutes les boîtes sauf `users`.

## Bonnes pratiques

### Initialisation à la demande

1. **Initialiser les boîtes uniquement lorsqu'elles sont nécessaires** :

   - N'ouvrir que les boîtes `users` et `settings` au démarrage
   - Initialiser les autres boîtes après connexion réussie
   - Utiliser `_ensureBoxIsOpen()` avant chaque accès à une boîte

2. **Centraliser la gestion des boîtes** :

   - Créer un service dédié à la gestion des boîtes Hive
   - Utiliser des méthodes comme `openRequiredBoxes()` et `clearAllBoxes()`

3. **Optimiser pour les différentes plateformes** :
   - Adapter le nettoyage selon la plateforme (Web, iOS, Android)
   - Utiliser des méthodes spécifiques comme `_clearIndexedDB()` pour le web

### Éviter l'erreur "Box has already been closed"

1. **Ne jamais fermer une boîte qui pourrait être utilisée plus tard** :

   - Utiliser `_ensureBoxIsOpen()` au lieu de fermer et rouvrir les boîtes
   - Vider les boîtes avec `box.clear()` au lieu de les fermer

2. **Vérifier qu'une boîte est ouverte avant de l'utiliser** :

   ```dart
   if (!Hive.isBoxOpen(boxName)) {
     await Hive.openBox<T>(boxName);
   }
   ```

3. **Gestion des erreurs robuste** :
   - Toujours entourer les opérations Hive de blocs try/catch
   - Prévoir des mécanismes de récupération en cas d'erreur

### Méthode utilitaire \_ensureBoxIsOpen

Cette méthode est cruciale pour garantir qu'une boîte est ouverte avant de l'utiliser :

```dart
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.userBoxName) {
        await Hive.openBox<UserModel>(boxName);
      } else {
        await Hive.openBox(boxName);
      }
      debugPrint('Boîte $boxName ouverte avec succès');
    }
  } catch (e) {
    debugPrint('Erreur lors de l\'ouverture de la boîte $boxName: $e');
    throw Exception('Impossible d\'ouvrir la boîte $boxName: $e');
  }
}
```

---

Ce guide devrait aider à comprendre et maintenir la gestion des boîtes Hive dans l'application GeoSector. Pour toute question ou problème, consultez la documentation de Hive ou contactez l'équipe de développement.
