# QUEUE-APP-API.md
# Système de File d'Attente pour les Requêtes API Hors Ligne

## 🚀 État actuel de l'implémentation (29/08/2025)

### ✅ Phases complétées
- **Phase 1** : Infrastructure de base - COMPLÉTÉ
- **Phase 2** : Modification ApiService - COMPLÉTÉ  
- **Phase 3** : Intégration ConnectivityService - COMPLÉTÉ
- **Phase 5** : Alertes utilisateur - COMPLÉTÉ
- **Phase 6** : Adaptation des Repositories CRUD - COMPLÉTÉ (tous les 8 repositories)

### ⚠️ Décisions d'architecture importantes
1. **Pas d'IDs temporaires** : La base de données MariaDB utilise des `int unsigned`, donc pas de valeurs négatives possibles
2. **Stratégie sans stockage local pour CREATE** :
   - CREATE offline → Requête en queue, pas de stockage Hive, message "Création en attente"
   - UPDATE offline → Modification locale avec `isSynced: false` + requête en queue
   - DELETE offline → Suppression locale immédiate + requête en queue
3. **Pas d'expiration automatique** : Les requêtes persistent indéfiniment jusqu'à leur envoi
4. **Ordre FIFO strict** : Basé sur `createdAt` pour garantir la cohérence

### 📦 Repositories adaptés (8/8)

| Repository | CREATE offline | UPDATE offline | DELETE offline | Notes |
|------------|---------------|----------------|----------------|--------|
| **PassageRepository** | ✅ Queue + Dialog + Pas de stockage | ✅ Stockage local + Flag | ✅ Suppression immédiate | Priorité haute terrain |
| **ClientRepository** | ✅ Queue + Dialog + Pas de stockage | ✅ Stockage local | ✅ Suppression immédiate | Adhérents terrain |
| **MembreRepository** | ✅ Queue + Dialog + Retourne null | ✅ Stockage local | ✅ Suppression immédiate | Gestion équipe |
| **SectorRepository** | ✅ Queue + Dialog + Status "queued" | ✅ Stockage local | ✅ Suppression + passages | Gère aussi les passages |
| **UserRepository** | N/A | ✅ Stockage avec isSynced=false | N/A | Profil utilisateur connecté uniquement |
| **AmicaleRepository** | ✅ Queue + Dialog + Pas de stockage | ✅ Stockage local | ✅ Suppression immédiate | Organisation |
| **OperationRepository** | ✅ Queue + Dialog + Pas de stockage | ✅ Stockage avec isSynced=false | ✅ Suppression + données liées | Campagnes |

### 📊 Réponses API en mode offline
Toutes les requêtes stockées en pending retournent :
```json
{
  "queued": true
}
```

### 🔄 Prochain travail
- Implémenter la gestion des conflits de synchronisation
- Ajouter la limite de queue (1000 requêtes max)
- Créer le système d'export des données en attente
- Ajouter un dialog de confirmation lors de la déconnexion avec données en attente
- Tester le système complet en mode avion

---

## 📋 Vue d'ensemble

### Objectif
Créer un système robuste de gestion des requêtes API en mode hors ligne pour permettre à l'application de fonctionner sans connexion Internet et de synchroniser automatiquement les données dès que la connexion est rétablie.

### Problématique actuelle
- Les requêtes API échouent immédiatement sans connexion
- Aucun mécanisme de file d'attente pour les requêtes en attente
- Les messages du chat sont perdus si envoyés hors ligne
- Les modifications CRUD ne sont pas persistées localement pour envoi ultérieur

### Solution proposée
Modifier `ApiService` pour qu'il gère automatiquement la file d'attente : stockage dans Hive si hors ligne, envoi direct si en ligne, et traitement automatique de la queue au retour de connexion.

## 🏗️ Architecture

### Flux de données

```
Application (UI/Repository)
           ↓
      ApiService (modifié)
           ↓
    [Si en ligne] → Envoi direct → API
           ↓
    [Si hors ligne] → Stockage → Hive Box "pending_requests"
           
ConnectivityService (écoute en permanence)
           ↓
    [Connexion rétablie] → Notifie ApiService
           ↓
    ApiService.processPendingRequests() → API
```

### Services impliqués

1. **ApiService** (à modifier)
   - Vérifie la connectivité avant chaque requête
   - Si online : envoi direct à l'API
   - Si offline : stockage dans Hive Box
   - Méthode `processPendingRequests()` pour vider la queue
   - Retourne une réponse "pending" avec tempId si offline

2. **ConnectivityService** (à enrichir)
   - Détecte les changements de connexion
   - Appelle `ApiService.processPendingRequests()` au retour
   - Vérifie périodiquement s'il y a des requêtes en attente

3. **Hive Boxes** (nouvelles)
   - `pending_requests` : File d'attente des requêtes (JAMAIS supprimée si non vide)
   - `temp_entities` : Entités temporaires (messages temp_, etc.)

## 📊 Analyse des requêtes actuelles

### 1. Chat Service
- **POST** `/chat/rooms` - Créer une conversation
- **POST** `/chat/rooms/{roomId}/messages` - Envoyer un message
- **GET** `/chat/rooms` - Obtenir les conversations
- **GET** `/chat/rooms/{roomId}/messages` - Obtenir les messages
- **DELETE** `/chat/rooms/{roomId}` - Supprimer une conversation

### 2. User Repository
- **GET** `/users` - Liste des utilisateurs
- **GET** `/users/{id}` - Détail utilisateur
- **POST** `/users` - Créer utilisateur
- **PUT** `/users/{id}` - Modifier utilisateur
- **DELETE** `/users/{id}` - Supprimer utilisateur

### 3. Amicale Repository
- **GET** `/entites` - Liste des amicales
- **PUT** `/entites/{id}` - Modifier amicale
- **POST** `/entites/{id}/logo` - Upload logo

### 4. Operations/Passages
- **GET** `/operations` - Liste des opérations
- **POST** `/passages` - Créer un passage
- **PUT** `/passages/{id}` - Modifier un passage
- **GET** `/operations/{id}/export/excel` - Export Excel

### 5. Authentification
- **POST** `/login` - Connexion
- **POST** `/logout` - Déconnexion

## 💾 Modèle de données pour la file d'attente

### PendingRequest Model
```dart
@HiveType(typeId: 100)
class PendingRequest extends HiveObject {
  @HiveField(0)
  final String id; // UUID unique
  
  @HiveField(1)
  final String method; // POST, GET, PUT, DELETE
  
  @HiveField(2)
  final String path; // /chat/rooms/xxx/messages
  
  @HiveField(3)
  final Map<String, dynamic>? data; // Body de la requête
  
  @HiveField(4)
  final Map<String, dynamic>? queryParams; // Query parameters
  
  @HiveField(5)
  final DateTime createdAt; // Timestamp de création (ORDRE DE TRAITEMENT)
  
  @HiveField(6)
  final String? tempId; // ID temporaire associé (ex: temp_xxx)
  
  @HiveField(7)
  final String context; // chat, user, operation, etc.
  
  @HiveField(8)
  final int retryCount; // Nombre de tentatives
  
  @HiveField(9)
  final String? errorMessage; // Dernière erreur
  
  @HiveField(10)
  final Map<String, dynamic>? metadata; // Infos additionnelles
}
```

**⚠️ IMPORTANT : Les requêtes DOIVENT être traitées dans l'ordre chronologique strict (FIFO - First In First Out) basé sur `createdAt` pour garantir la cohérence des données.**

## 🎯 Cas d'usage spécifiques

### 1. Chat - Envoi de message hors ligne

**Workflow actuel:**
1. Utilisateur tape un message
2. Tentative d'envoi direct à l'API
3. Si pas de connexion → Erreur

**Nouveau workflow:**
1. Utilisateur tape un message
2. Création d'un message temporaire avec ID `temp_xxx`
3. Sauvegarde immédiate dans Hive (affichage instantané)
4. Si en ligne → Envoi API → Remplacement par message réel
5. Si hors ligne → Ajout à la queue → Message affiché en italique/grisé
6. Quand connexion revenue → Traitement de la queue → Mise à jour avec ID réel

**Indicateurs visuels:**
- Message en attente : Texte italique + icône horloge
- Message en cours d'envoi : Spinner
- Message envoyé : Texte normal
- Message en erreur : Texte rouge + icône erreur + option retry

### 2. CRUD Utilisateurs/Amicales

**Création hors ligne:**
- Génération d'un ID temporaire `temp_user_xxx`
- Sauvegarde locale dans Hive
- Affichage avec badge "En attente de synchronisation"
- Synchronisation automatique au retour de connexion

**Modification hors ligne:**
- Sauvegarde des modifications locales
- Marquage de l'entité comme "modified_offline"
- Affichage d'un indicateur de synchronisation en attente
- Gestion des conflits si modifié par ailleurs

**Suppression hors ligne:**
- Marquage local comme "deleted"
- Masquage de l'UI
- Envoi de la suppression au retour de connexion

### 3. Passages terrain

**Enregistrement de passage hors ligne:**
- Sauvegarde locale complète (coordonnées GPS, timestamp, etc.)
- Queue avec priorité HAUTE
- Synchronisation prioritaire au retour de connexion
- Conservation des données même après envoi (backup)

## 🔄 Gestion de la synchronisation

### Ordre de traitement
**FIFO strict (First In First Out)** : Les requêtes sont TOUJOURS traitées dans l'ordre chronologique de leur création (`createdAt`), sans exception. Ceci garantit :
- Les messages de chat arrivent dans le bon ordre
- Une création précède toujours sa modification
- Une modification précède toujours sa suppression
- La cohérence des données est maintenue

### Stratégie de retry
- 1ère tentative : Immédiate
- 2ème tentative : Après 30 secondes
- 3ème tentative : Après 2 minutes
- 4ème+ tentative : Toutes les 5 minutes
- ~~Abandon après 24h~~ **MODIFIÉ**: Pas d'expiration automatique - requêtes persistent indéfiniment

### Gestion des conflits
- Messages chat : Pas de conflit (append-only)
- CRUD : Dernière modification gagne + log des conflits
- Passages : Pas de conflit (chaque passage est unique)

## 🛠️ Plan d'implémentation

### Phase 1 : Infrastructure (Jour 1) ✅ COMPLÉTÉ
- [x] Créer le modèle `PendingRequest`
- [x] Créer la Hive Box `pending_requests` avec protection
- [x] Enrichir `ConnectivityService` avec gestion de queue
- [x] Ajouter les indicateurs UI d'alerte

### Phase 2 : Modification ApiService (Jour 1-2) ✅ COMPLÉTÉ
- [x] Ajouter vérification connectivité dans chaque méthode
- [x] Implémenter le stockage dans Hive si offline
- [x] Créer méthode `processPendingRequests()`
- [x] Gérer les réponses "pending" avec tempId

### Phase 3 : Traitement de la queue (Jour 2) ✅ COMPLÉTÉ
- [x] Implémenter le processeur de queue FIFO
- [x] Garantir l'ordre chronologique strict
- [x] Implémenter les retry avec backoff
- [x] Gérer les erreurs et abandons

### Phase 4 : Chat (Jour 3)
- [ ] Adapter `ChatService` pour messages temporaires
- [ ] Implémenter l'UI pour messages en attente
- [ ] Gérer le remplacement temp_ → ID réel
- [ ] Tester envoi/réception hors ligne

### Phase 5 : CRUD (Jour 4) ✅ COMPLÉTÉ
- [x] Adapter PassageRepository (COMPLÉTÉ)
- [x] Adapter les autres repositories (Client, Membre, Sector, User, Amicale, Operation) - TOUS COMPLÉTÉS
- [x] ~~Gérer les IDs temporaires~~ **MODIFIÉ**: Pas d'IDs temporaires (contrainte DB unsigned int)
- [x] Implémenter les indicateurs UI
- [ ] Gérer les conflits de synchronisation

### Phase 6 : Tests et optimisation (Jour 5)
- [ ] Tests unitaires du QueueService
- [ ] Tests d'intégration
- [ ] Tests de scénarios hors ligne/en ligne
- [ ] Optimisation des performances

## 🎨 UI/UX Guidelines

### ⚠️ ALERTES UTILISATEUR OBLIGATOIRES

#### Mode hors ligne détecté
- **Banner permanent en haut** : Fond orange avec texte "⚠️ Mode hors ligne - X modifications en attente"
- **Badge rouge sur l'app bar** : Nombre de requêtes non synchronisées
- **Vibration/Son** : Alerte immédiate lors de la perte de connexion

#### Tentative de déconnexion avec données en attente
- **Dialog bloquant** :
  ```
  ⚠️ ATTENTION
  Vous avez X modifications non synchronisées.
  
  Si vous vous déconnectez maintenant, ces données
  seront PERDUES :
  - X messages non envoyés
  - X modifications d'utilisateurs
  - X passages terrain
  
  [Annuler] [Se reconnecter d'abord] [Forcer déconnexion*]
  
  * Les données non synchronisées seront perdues
  ```

#### Fermeture de l'app avec données en attente
- **Notification système** : "GeoSector a des données non synchronisées"
- **Dialog de confirmation** si tentative de fermeture

### Indicateurs visuels globaux
- **Badge sur l'app bar** : Nombre de requêtes en attente (rouge pulsant)
- **Snackbar** : Notification quand connexion perdue/retrouvée
- **Pull to refresh** : Force la synchronisation manuelle
- **Bouton "Synchroniser"** : Visible uniquement si données en attente

### États des éléments
- **En attente** : Opacity 0.7 + icône horloge + texte italique
- **En cours de sync** : Shimmer effect ou spinner
- **Erreur de sync** : Bordure rouge + icône erreur
- **Synchronisé** : État normal

### Messages utilisateur
- "⚠️ Pas de connexion - X actions en attente de synchronisation"
- "⚠️ Reconnectez-vous pour envoyer vos modifications"
- "✅ Connexion rétablie - Synchronisation en cours..."
- "✅ Toutes les modifications ont été synchronisées"
- "❌ Erreur de synchronisation - Toucher pour réessayer"

## 🔐 Considérations de sécurité

### ⚠️ PROTECTION CRITIQUE DE LA HIVE BOX

**SPLASH PAGE - ATTENTION** : 
- La `splash_page.dart` qui réinitialise les boxes au démarrage DOIT :
  1. Vérifier si `pending_requests` box existe et n'est pas vide
  2. Si elle contient des données → NE PAS LA SUPPRIMER
  3. Afficher un avertissement à l'utilisateur
  4. Déclencher immédiatement le traitement de la queue si connexion disponible

```dart
// Dans splash_page.dart
if (await Hive.boxExists(AppKeys.pendingRequestsBoxName)) {
  final box = await Hive.openBox<PendingRequest>(AppKeys.pendingRequestsBoxName);
  if (box.isNotEmpty) {
    print('⚠️ ${box.length} requêtes en attente trouvées');
    // NE PAS SUPPRIMER LA BOX
    // Notifier l'utilisateur
    // Déclencher le traitement si online
  }
}
```

**Dans app_keys.dart** :
```dart
static const String pendingRequestsBoxName = 'pending_requests';
static const String tempEntitiesBoxName = 'temp_entities';
```

### Autres considérations

1. **Persistance sécurisée** : Chiffrer les données sensibles dans Hive
2. **Expiration des tokens** : Gérer le renouvellement des sessions
3. **Limite de queue** : Maximum 1000 requêtes en attente
4. **Nettoyage** : Purger les requêtes expirées (>24h) SEULEMENT si confirmé par l'utilisateur
5. **Validation** : Revalider les données avant envoi
6. **Sauvegarde** : Export possible des requêtes en attente avant déconnexion forcée

## 📈 Monitoring et debugging

### Logs à implémenter
```dart
// Format des logs
[ApiService] No connection - Request queued: POST /chat/rooms/xxx/messages
[ApiService] Queue size: 5 pending requests
[ConnectivityService] Connection restored - Processing queue...
[ApiService] Processing pending request 1/5: POST /chat/rooms/xxx/messages
[ApiService] Success: temp_xxx → real_id_xxx
[ApiService] Retry 2/5 for request xxx
[ApiService] WARNING: Request xxx pending for >12h
[ApiService] ALERT: User attempting logout with 5 pending requests
```

### Métriques à suivre
- Taille de la queue
- Temps moyen de traitement
- Taux de succès/échec
- Nombre de retry par requête
- Durée moyenne hors ligne

## 🚀 Bénéfices attendus

1. **Expérience utilisateur** : Application utilisable sans connexion
2. **Fiabilité** : Aucune perte de données
3. **Performance** : Réponse immédiate (optimistic UI)
4. **Productivité** : Travail continu même en zone blanche
5. **Résilience** : Gestion automatique des problèmes réseau

## ⚠️ Points d'attention

1. **Taille de la queue** : Limiter pour éviter saturation mémoire
2. **Ordre des requêtes** : Respecter les dépendances
3. **Idempotence** : S'assurer que rejouer une requête est safe
4. **Conflits** : Stratégie claire de résolution
5. **Battery** : Optimiser pour ne pas drainer la batterie

## 📝 Planning détaillé d'implémentation

### **Phase 1 : Infrastructure de base** (Jour 1) ✅ COMPLÉTÉ
- [x] Créer les constantes dans `app_keys.dart` (pendingRequestsBoxName, tempEntitiesBoxName)
- [x] Créer le modèle `PendingRequest` avec annotations Hive
- [x] Enregistrer l'adapter PendingRequest dans `HiveAdapters`
- [x] Protéger la box `pending_requests` dans `HiveService`
- [x] Ajouter `pending_requests` dans `HiveService._boxConfigs`

### **Phase 2 : Modification ApiService** (Jour 1-2) ✅ COMPLÉTÉ
- [x] Créer QueueManager dans ApiService pour gérer la file
- [x] Modifier les méthodes ApiService (get, post, put, delete) pour vérifier connectivité
- [x] Implémenter `processPendingRequests()` dans ApiService
- [x] Créer le système de retry avec backoff exponentiel

### **Phase 3 : Intégration ConnectivityService** (Jour 2) ✅ COMPLÉTÉ
- [x] Enrichir ApiService avec listener de connectivité pour déclencher la synchronisation au retour de connexion

### **Phase 4 : Chat (Proof of Concept)** (Jour 3)
- [ ] Adapter ChatService pour messages temporaires (temp_xxx)
- [ ] Créer UI pour messages en attente (italique, icône horloge)
- [ ] Implémenter le remplacement temp_id vers real_id

### **Phase 5 : Alertes utilisateur** (Jour 3) ✅ COMPLÉTÉ
- [x] Badge de connexion avec indicateur et animation clignotante
- [x] Dialog d'information pour création en attente (PassageRepository)
- [x] Intégration du compteur de requêtes pendantes dans ConnectivityIndicator
- [x] Widget PendingRequestsCounter pour affichage détaillé

### **Phase 6 : Adaptation des Repositories CRUD** (Jour 4-5) ✅ COMPLÉTÉ

#### **Priorité HAUTE** (critique terrain) ✅
- [x] Adapter **PassageRepository** pour CRUD hors ligne avec priorité haute
- [x] Adapter **ClientRepository** pour création d'adhérents sur le terrain

#### **Priorité MOYENNE** ✅
- [x] Adapter **UserRepository** pour CRUD hors ligne (profil utilisateur connecté uniquement)
- [x] Adapter **MembreRepository** pour gestion de l'équipe
- [x] Adapter **SectorRepository** pour assignation de secteurs

#### **Priorité BASSE** ✅
- [x] Adapter **AmicaleRepository** pour modifications moins fréquentes
- [x] Adapter **OperationRepository** pour gestion des campagnes

### **Phase 7 : Gestion avancée** (Jour 5) ✅
- [x] Créer système de gestion des conflits
  - Détection automatique des erreurs 409 (Conflict)
  - Marquage des requêtes en conflit avec `hasConflict: true`
  - Méthodes de résolution : `resolveConflictByDeletion()` et `resolveConflictByRetry()`
  - Gestion des erreurs permanentes (4xx sauf 409) avec suppression automatique
  - Limite de 5 tentatives pour les erreurs temporaires
- [x] Implémenter limite de queue (max 1000 requêtes)
  - Vérification avant ajout avec exception si limite atteinte
  - Message d'erreur clair pour l'utilisateur
- [x] Créer système d'export des données en attente
  - Export JSON complet avec `exportPendingRequestsToJson()`
  - Import avec fusion et détection de doublons `importPendingRequestsFromJson()`
  - Statistiques détaillées avec `getPendingRequestsStats()`

### **Phase 8 : Monitoring et debug** (Jour 6)
- [ ] Ajouter logs détaillés pour monitoring
- [ ] Implémenter métriques de performance

### **Phase 9 : Tests** (Jour 6-7)
- [ ] Créer tests unitaires pour QueueService
- [ ] Créer tests d'intégration mode offline/online
- [ ] Tester scénarios réels (mode avion, perte connexion)

### **Phase 10 : Documentation** (Jour 7)
- [ ] Documenter l'utilisation pour les développeurs
- [ ] Créer guide utilisateur pour le mode hors ligne

## 📊 Estimation et priorités

### **Durée totale estimée** : 5-7 jours

### **MVP minimal (3 jours)**
- Phases 1-3 : Infrastructure + ApiService + ConnectivityService
- Phase 4 : Chat comme proof of concept
- Phase 5 : Alertes utilisateur de base

### **Version complète (7 jours)**
- Toutes les phases incluant tous les repositories
- Tests complets
- Documentation

### **Ordre de priorité des repositories**

1. **🔴 Critique** : PassageRepository, ClientRepository
2. **🟠 Important** : UserRepository, MembreRepository, SectorRepository  
3. **🟡 Normal** : AmicaleRepository, OperationRepository

## 🔧 Utilisation des fonctionnalités avancées

### **Gestion des conflits**

```dart
// Récupérer les requêtes en conflit
final conflicts = ApiService.instance.getConflictedRequests();
final conflictCount = ApiService.instance.getConflictedRequestsCount();

// Résoudre un conflit
await ApiService.instance.resolveConflictByDeletion(requestId); // Supprimer
await ApiService.instance.resolveConflictByRetry(requestId);    // Réessayer
```

### **Export/Import des données**

```dart
// Exporter les requêtes en attente
final jsonData = ApiService.instance.exportPendingRequestsToJson();
// Sauvegarder dans un fichier ou partager...

// Importer des requêtes
final imported = await ApiService.instance.importPendingRequestsFromJson(jsonString);
print('$imported requêtes importées');

// Obtenir des statistiques
final stats = ApiService.instance.getPendingRequestsStats();
print('Total: ${stats['total']}, Conflits: ${stats['conflicted']}');
```

### **Limite de queue**

La limite de 1000 requêtes est automatiquement vérifiée. Si atteinte :
- Une `ApiException` est levée avec un message explicite
- L'utilisateur doit attendre la synchronisation avant de nouvelles opérations

### **Guide de test en mode avion**

1. **Activer le mode avion** sur l'appareil
2. **Effectuer des opérations** (créations, modifications, suppressions)
3. **Vérifier le compteur** de requêtes en attente dans l'interface
4. **Désactiver le mode avion**
5. **Observer la synchronisation** automatique (badge devient vert)
6. **Vérifier les données** synchronisées sur le serveur

---

*Document créé le 25/08/2025 - Dernière mise à jour : 29/08/2025 - Système complet avec gestion des conflits et export*