# Module Chat - Documentation API

## Vue d'ensemble

Le module Chat permet aux utilisateurs de l'application GeoSector de communiquer entre eux via une messagerie intégrée. Il supporte les conversations privées, de groupe et les diffusions (broadcast).

## Architecture

### Tables de base de données

- `chat_rooms` : Salles de conversation
- `chat_messages` : Messages échangés
- `chat_participants` : Participants aux conversations
- `chat_read_receipts` : Accusés de lecture

### Permissions par rôle

| Rôle | Permissions |
|------|------------|
| **1 - Utilisateur** | Conversations privées et groupes avec membres de son entité |
| **2 - Admin entité** | Toutes conversations de son entité + création de diffusions |
| **> 2 - Super admin** | Accès total à toutes les conversations |

## Flux d'utilisation du module Chat

### 📱 Vue d'ensemble du flux

Le module Chat fonctionne en mode **chargement dynamique** : les données sont récupérées à la demande, pas toutes en une fois au login.

### 1. Au login (`/api/login`)

La réponse du login contient un objet `chat` avec les informations de base :

```json
{
  "status": "success",
  "user": {...},
  "amicale": {...},
  "chat": {
    "total_rooms": 5,           // Nombre total de conversations
    "unread_messages": 12,       // Total messages non lus
    "chat_enabled": true,        // Module activé pour cet utilisateur
    "last_active_room": {        // Dernière conversation active
      "id": "uuid-room-123",
      "title": "Discussion équipe",
      "type": "group",
      "last_message": "À demain !",
      "last_message_at": "2025-01-17 18:30:00"
    }
  }
}
```

→ Permet d'afficher un **badge de notification** et de savoir si le chat est disponible

### 2. Ouverture de la page Chat

#### Étape 1 : Chargement initial
```
GET /api/chat/rooms
```
→ Récupère la liste des conversations avec aperçu du dernier message

#### Étape 2 : Sélection d'une conversation
```
GET /api/chat/rooms/{room_id}/messages?limit=50
```
→ Charge les 50 derniers messages (pagination disponible)

#### Étape 3 : Marquage comme lu
```
POST /api/chat/rooms/{room_id}/read
```
→ Met à jour les compteurs de messages non lus

### 3. Actions utilisateur

| Action | Endpoint | Description |
|--------|----------|-------------|
| **Envoyer un message** | `POST /api/chat/rooms/{id}/messages` | Envoie et retourne le message créé |
| **Créer une conversation** | `POST /api/chat/rooms` | Crée une nouvelle room |
| **Obtenir les destinataires** | `GET /api/chat/recipients` | Liste des contacts disponibles |
| **Charger plus de messages** | `GET /api/chat/rooms/{id}/messages?before={msg_id}` | Pagination |

### 4. Stratégies de rafraîchissement

#### Polling (recommandé pour débuter)
- Rafraîchir `/api/chat/rooms` toutes les 30 secondes
- Rafraîchir les messages de la conversation active toutes les 10 secondes

#### Pull to refresh
- Permettre à l'utilisateur de rafraîchir manuellement

#### Lifecycle events
- Recharger quand l'app revient au premier plan
- Rafraîchir après envoi d'un message

### 5. Exemple d'implémentation Flutter

```dart
class ChatService {
  Timer? _roomsTimer;
  Timer? _messagesTimer;
  
  // 1. Au login, stocker les infos de base
  void initFromLogin(Map<String, dynamic> chatData) {
    _unreadCount = chatData['unread_messages'];
    _chatEnabled = chatData['chat_enabled'];
    notifyListeners();
  }
  
  // 2. À l'ouverture du chat
  Future<void> openChatPage() async {
    // Charger les conversations
    final rooms = await api.get('/api/chat/rooms');
    _rooms = rooms['rooms'];
    
    // Démarrer le polling
    _startPolling();
  }
  
  // 3. Sélection d'une conversation
  Future<void> selectRoom(String roomId) async {
    // Charger les messages
    final response = await api.get('/api/chat/rooms/$roomId/messages');
    _currentMessages = response['messages'];
    
    // Marquer comme lu
    await api.post('/api/chat/rooms/$roomId/read');
    
    // Rafraîchir plus fréquemment cette conversation
    _startMessagePolling(roomId);
  }
  
  // 4. Polling automatique
  void _startPolling() {
    _roomsTimer = Timer.periodic(Duration(seconds: 30), (_) {
      _refreshRooms();
    });
  }
  
  // 5. Nettoyage
  void dispose() {
    _roomsTimer?.cancel();
    _messagesTimer?.cancel();
  }
}
```

## Endpoints API

### 1. GET /api/chat/rooms
**Description** : Récupère la liste des conversations de l'utilisateur

**Réponse** :
```json
{
  "status": "success",
  "rooms": [
    {
      "id": "uuid-room-1",
      "title": "Discussion équipe",
      "type": "group",
      "created_at": "2025-01-17 10:00:00",
      "created_by": 123,
      "updated_at": "2025-01-17 14:30:00",
      "last_message": "Bonjour tout le monde",
      "last_message_at": "2025-01-17 14:30:00",
      "unread_count": 3,
      "participant_count": 5,
      "participants": [
        {
          "user_id": 123,
          "name": "Jean Dupont",
          "first_name": "Jean",
          "is_admin": true
        }
      ]
    }
  ]
}
```

### 2. POST /api/chat/rooms
**Description** : Crée une nouvelle conversation

**Body** :
```json
{
  "type": "private|group|broadcast",
  "title": "Titre optionnel (requis pour group/broadcast)",
  "participants": [456, 789],  // IDs des participants
  "initial_message": "Message initial optionnel"
}
```

**Règles** :
- `private` : Maximum 2 participants (incluant le créateur)
- `group` : Plusieurs participants possibles
- `broadcast` : Réservé aux admins (rôle >= 2)

**Réponse** :
```json
{
  "status": "success",
  "room": {
    "id": "uuid-new-room",
    "title": "Nouvelle conversation",
    "type": "group",
    "created_at": "2025-01-17 15:00:00",
    "participants": [...]
  },
  "existing": false  // true si conversation privée existante trouvée
}
```

### 3. GET /api/chat/rooms/{id}/messages
**Description** : Récupère les messages d'une conversation

**Paramètres** :
- `limit` : Nombre de messages (défaut: 50, max: 100)
- `before` : ID du message pour pagination

**Réponse** :
```json
{
  "status": "success",
  "messages": [
    {
      "id": "uuid-message-1",
      "content": "Bonjour !",
      "sender_id": 123,
      "sender_name": "Jean Dupont",
      "sender_first_name": "Jean",
      "sent_at": "2025-01-17 14:00:00",
      "edited_at": null,
      "is_deleted": false,
      "is_read": true,
      "is_mine": false,
      "read_count": 3
    }
  ],
  "has_more": true
}
```

### 4. POST /api/chat/rooms/{id}/messages
**Description** : Envoie un message dans une conversation

**Body** :
```json
{
  "content": "Contenu du message (max 5000 caractères)"
}
```

**Réponse** :
```json
{
  "status": "success",
  "message": {
    "id": "uuid-new-message",
    "content": "Message envoyé",
    "sender_id": 123,
    "sender_name": "Jean Dupont",
    "sent_at": "2025-01-17 15:30:00",
    "is_mine": true,
    "is_read": false,
    "read_count": 0
  }
}
```

### 5. POST /api/chat/rooms/{id}/read
**Description** : Marque les messages comme lus

**Body (optionnel)** :
```json
{
  "message_ids": ["uuid-1", "uuid-2"]  // Si omis, marque tous les messages
}
```

**Réponse** :
```json
{
  "status": "success",
  "unread_count": 0  // Nombre de messages non lus restants
}
```

### 6. GET /api/chat/recipients
**Description** : Liste des destinataires possibles pour créer une conversation

**Réponse** :
```json
{
  "status": "success",
  "recipients": [
    {
      "id": 456,
      "name": "Marie Martin",
      "first_name": "Marie",
      "role": 1,
      "entite_id": 5
    }
  ],
  "recipients_by_entity": {
    "Amicale de Grenoble": [
      {...}
    ],
    "Amicale de Lyon": [
      {...}
    ]
  }
}
```

## Fonctionnalités clés

### 1. Types de conversations

#### Private (Conversation privée)
- Entre 2 utilisateurs uniquement
- Détection automatique de conversation existante
- Pas de titre requis

#### Group (Groupe)
- Plusieurs participants
- Titre optionnel mais recommandé
- Admin de groupe (créateur)

#### Broadcast (Diffusion)
- Réservé aux admins (rôle >= 2)
- Communication unidirectionnelle possible
- Pour annonces importantes

### 2. Gestion des permissions

Le système vérifie automatiquement :
- L'appartenance à une conversation avant lecture/écriture
- Les droits de création selon le type de conversation
- La visibilité des destinataires selon le rôle

### 3. Statuts de lecture

- **Accusés de lecture individuels** : Chaque message peut être marqué comme lu
- **Compteur de non-lus** : Par conversation et global
- **Last read** : Timestamp de dernière lecture par participant

### 4. Optimisations

- **Pagination** : Chargement progressif des messages
- **Index optimisés** : Pour les requêtes fréquentes
- **Vue SQL** : Pour récupération rapide du dernier message

## Sécurité

### Chiffrement
- Les noms d'utilisateurs sont stockés chiffrés (AES-256)
- Déchiffrement à la volée lors de la lecture

### Validation
- Longueur maximale des messages : 5000 caractères
- Trim automatique du contenu
- Vérification des permissions à chaque action

### Isolation
- Les utilisateurs ne voient que leurs conversations autorisées
- Filtrage par entité selon le rôle
- Soft delete pour conservation de l'historique

## Migration

Exécuter le script SQL :
```bash
mysql -u root -p geo_app < scripts/sql/create_chat_tables.sql
```

## Évolutions futures possibles

1. **Notifications push** : Intégration avec Firebase/WebSocket
2. **Fichiers joints** : Support d'images et documents
3. **Réactions** : Emojis sur les messages
4. **Mentions** : @username pour notifier
5. **Recherche** : Dans l'historique des messages
6. **Chiffrement E2E** : Pour conversations sensibles
7. **Statuts de présence** : En ligne/Hors ligne
8. **Indicateur de frappe** : "X est en train d'écrire..."

## Tests

### Cas de test recommandés

1. **Création de conversation privée**
   - Vérifier la détection de conversation existante
   - Tester avec utilisateurs de différentes entités

2. **Envoi de messages**
   - Messages avec caractères UTF-8 (émojis, accents)
   - Messages très longs (limite 5000)
   - Messages vides (doivent être rejetés)

3. **Marquage comme lu**
   - Marquer messages spécifiques
   - Marquer tous les messages d'une room
   - Vérifier les compteurs

4. **Permissions**
   - Utilisateur simple ne peut pas créer de broadcast
   - Accès refusé aux conversations non autorisées
   - Filtrage correct des destinataires

## Support

Pour toute question ou problème :
- Vérifier les logs dans `/logs/`
- Consulter les tables `chat_*` en base de données
- Tester avec les scripts de test fournis