# Solution de Chat pour Applications Flutter

## Présentation générale

Cette solution propose un système de chat personnalisé et autonome pour des applications Flutter, avec possibilité d'intégration web. Elle est conçue pour fonctionner dans deux contextes différents :

1. **Chat entre utilisateurs authentifiés** (cas Geosector) : communications one-to-one ou en groupe entre utilisateurs déjà enregistrés dans la base de données.
2. **Chat entre professionnels et visiteurs anonymes** (cas Resalice) : communications initiées par des visiteurs anonymes qui peuvent ensuite être convertis en clients référencés.

## Architecture technique

### 1. Structure générale

La solution s'articule autour de quatre composants principaux :

- **Module Flutter** : Widgets et logique pour l'interface utilisateur mobile
- **Module Web** : Composants pour l'intégration web (compatible avec Flutter Web ou sites traditionnels)
- **API Backend** : Endpoints REST uniquement pour la récupération de l'historique des conversations
- **Module Go Chat Service** : Service de gestion des messages MQTT, modération et synchronisation avec la base de données

### 2. Infrastructure de notifications

#### Broker MQTT
Le système utilise MQTT pour les notifications en temps réel :
- Broker Mosquitto hébergé dans un container Incus
- Connexion sécurisée via SSL/TLS (port 8883)
- Authentification par username/password
- QoS 1 (at least once) pour garantir la livraison

#### Module Go Chat Service
Un service externe en Go qui :
- Écoute les événements MQTT
- Enregistre les messages dans la base de données
- Applique des règles de modération configurables
- Synchronise les notifications avec le stockage

```go
type ChatService struct {
    mqttClient    mqtt.Client
    db           *sql.DB
    moderator    *Moderator
    config       *ChatConfig
}

type ChatConfig struct {
    ApplicationID    string
    ModeratorEnabled bool
    BadWords         []string
    FloodLimits      int
    SpamRules        map[string]interface{}
    Webhooks         []string
}
```

### 3. Modèle de données

#### Entités principales

```
Conversation
  ├── id : Identifiant unique
  ├── type : Type de conversation (one_to_one, group, anonymous, broadcast, announcement)
  ├── title : Titre facultatif pour les groupes et obligatoire pour les annonces
  ├── reply_permission : Niveau de permission pour répondre (all, admins_only, sender_only, none)
  ├── created_at : Date de création
  ├── updated_at : Dernière mise à jour
  ├── is_pinned : Indique si la conversation est épinglée (pour annonces importantes)
  ├── expiry_date : Date d'expiration optionnelle (pour annonces temporaires)
  └── participants : Liste des participants

Message
  ├── id : Identifiant unique
  ├── conversation_id : ID de la conversation
  ├── sender_id : ID de l'expéditeur (null pour anonyme)
  ├── sender_type : Type d'expéditeur (user, anonymous, system)
  ├── content : Contenu du message
  ├── content_type : Type de contenu (text, image, file)
  ├── created_at : Date d'envoi
  ├── delivered_at : Date de réception
  ├── read_at : Date de lecture
  ├── status : Statut du message (sent, delivered, read, error)
  ├── is_announcement : Indique s'il s'agit d'une annonce officielle
  ├── is_moderated : Indique si le message a été modéré
  └── moderation_status : Statut de la modération (pending, approved, rejected)

Participant
  ├── id : Identifiant unique
  ├── conversation_id : ID de la conversation
  ├── user_id : ID de l'utilisateur (si authentifié)
  ├── anonymous_id : ID anonyme (pour Resalice)
  ├── role : Rôle (admin, member, read_only)
  ├── joined_at : Date d'ajout à la conversation
  ├── via_target : Indique si l'utilisateur est inclus via un AudienceTarget
  ├── can_reply : Possibilité explicite de répondre (override de reply_permission)
  └── last_read_message_id : ID du dernier message lu

AudienceTarget
  ├── id : Identifiant unique
  ├── conversation_id : ID de la conversation
  ├── target_type : Type de cible (role, entity, all, combined)
  ├── target_id : ID du rôle ou de l'entité ciblée (pour compatibility)
  ├── role_filter : Filtre de rôle pour le ciblage combiné ('all', '1', '2', etc.)
  ├── entity_filter : Filtre d'entité pour le ciblage combiné ('all', 'id_entité')
  └── created_at : Date de création

AnonymousUser (pour Resalice)
  ├── id : Identifiant unique
  ├── device_id : Identifiant du dispositif
  ├── name : Nom temporaire (si fourni)
  ├── email : Email (si fourni)
  ├── created_at : Date de création
  ├── converted_to_user_id : ID utilisateur après conversion
  └── metadata : Informations supplémentaires

ChatNotification
  ├── id : Identifiant unique
  ├── user_id : ID de l'utilisateur destinataire
  ├── message_id : ID du message
  ├── conversation_id : ID de la conversation
  ├── type : Type de notification
  ├── status : Statut (sent, delivered, read)
  ├── sent_at : Date d'envoi
  └── read_at : Date de lecture
```

### 4. Backend et API

#### Structure de l'API

L'API sera développée en PHP 8.3 pour s'intégrer avec vos systèmes existants :

```
/api/chat/conversations
  GET    - Liste des conversations de l'utilisateur
  POST   - Créer une nouvelle conversation

/api/chat/conversations/{id}
  GET    - Détails d'une conversation
  PUT    - Mettre à jour une conversation
  DELETE - Supprimer une conversation

/api/chat/conversations/{id}/messages
  GET    - Messages d'une conversation (pagination) - uniquement pour l'historique

/api/chat/conversations/{id}/participants
  GET    - Liste des participants
  POST   - Ajouter un participant
  DELETE - Retirer un participant

/api/chat/messages/{id}
  PUT    - Mettre à jour un message (ex: marquer comme lu)
  DELETE - Supprimer un message

/api/chat/anonymous
  POST   - Démarrer une conversation anonyme

# Nouveaux endpoints pour les annonces
/api/chat/announcements
  GET    - Liste des annonces pour l'utilisateur
  POST   - Créer une nouvelle annonce

/api/chat/announcements/{id}/stats
  GET    - Obtenir les statistiques de lecture (qui a lu/non lu)

/api/chat/audience-targets
  GET    - Obtenir les cibles disponibles pour l'utilisateur actuel

/api/chat/conversations/{id}/pin
  PUT    - Épingler/désépingler une conversation

/api/chat/conversations/{id}/reply-permission
  PUT    - Modifier les permissions de réponse

/api/chat/moderation/rules
  GET    - Obtenir les règles de modération
  PUT    - Mettre à jour les règles de modération
```

#### Synchronisation

Le système supporte deux flux de données distincts :

1. **Temps réel via MQTT** : 
   - Envoi de messages en temps réel
   - Notifications instantanées
   - Gestion via le module Go

2. **Récupération historique via REST** :
   - Chargement de l'historique des conversations
   - Synchronisation des anciens messages
   - Accès direct à la base de données

- Enregistrement local des messages avec Hive pour le fonctionnement hors ligne

### 5. Widgets Flutter

#### Widgets principaux

1. **ChatScreen** : Écran principal d'une conversation

   ```dart
   ChatScreen({
     required String conversationId,
     String? title,
     Widget? header,
     Widget? footer,
     bool enableAttachments = true,
     bool showTypingIndicator = true,
     bool enableReadReceipts = true,
     bool isAnnouncement = false,
     bool canReply = true,
   })
   ```

2. **ConversationsList** : Liste des conversations

   ```dart
   ConversationsList({
     List<ConversationModel>? conversations,
     bool loadFromHive = true,
     Function(ConversationModel)? onConversationSelected,
     bool showLastMessage = true,
     bool showUnreadCount = true,
     bool showAnnouncementBadge = true,
     bool showPinnedFirst = true,
     Widget? emptyStateWidget,
   })
   ```

3. **MessageBubble** : Bulle de message

   ```dart
   MessageBubble({
     required MessageModel message,
     bool showSenderInfo = true,
     bool showTimestamp = true,
     bool showStatus = true,
     bool isAnnouncement = false,
     double maxWidth = 300,
   })
   ```

4. **ChatInput** : Zone de saisie de message

   ```dart
   ChatInput({
     required Function(String) onSendText,
     Function(File)? onSendFile,
     Function(File)? onSendImage,
     bool enableAttachments = true,
     bool enabled = true,
     String hintText = 'Saisissez votre message...',
     String? disabledMessage = 'Vous ne pouvez pas répondre à cette annonce',
     int? maxLength,
   })
   ```

5. **AnonymousChatStarter** : Widget pour démarrer un chat anonyme (Resalice)

   ```dart
   AnonymousChatStarter({
     required Function(String?) onChatStarted,
     bool requireName = false,
     bool requireEmail = false,
     String buttonLabel = 'Démarrer une conversation',
     Widget? customForm,
   })
   ```

6. **AnnouncementComposer** : Widget pour créer des annonces (Geosector uniquement)

   ```dart
   AnnouncementComposer({
     required Function(Map<String, dynamic>) onSend,
     List<Map<String, dynamic>>? availableTargets,
     String? initialTitle,
     String? initialMessage,
     bool allowAttachments = true,
     bool allowPinning = true,
     List<String> replyPermissionOptions = const ['all', 'admins_only', 'sender_only', 'none'],
     String defaultReplyPermission = 'none',
     DateTime? expiryDate,
     bool isGeosector = true, // Active la sélection des destinataires
   })
   ```

### 6. Gestion des notifications MQTT

#### Service MQTT Flutter

```dart
class MqttNotificationService {
  final String mqttHost;
  final int mqttPort;
  final String mqttUsername;
  final String mqttPassword;
  
  Future<void> initialize({required String userId}) async {
    // Initialisation du client MQTT
    await _initializeMqttClient();
    // Abonnement aux topics de l'utilisateur
    _subscribeToUserTopics(userId);
  }
  
  void _subscribeToUserTopics(String userId) {
    // Topics pour les messages personnels
    client.subscribe('chat/user/$userId/messages', MqttQos.atLeastOnce);
    // Topics pour les annonces
    client.subscribe('chat/announcement', MqttQos.atLeastOnce);
  }
  
  Future<void> _handleMessage(String topic, Map<String, dynamic> data) async {
    // Traitement et affichage de la notification locale
    await _showLocalNotification(data);
    // Stockage local pour la synchronisation
    await _syncWithHive(data);
  }
  
  // Pour envoyer un message en temps réel
  Future<void> sendMessage(String conversationId, String content) async {
    final message = {
      'conversationId': conversationId,
      'content': content,
      'senderId': currentUserId,
      'timestamp': DateTime.now().toIso8601String(),
    };
    
    await client.publishMessage(
      'chat/message/send',
      MqttQos.atLeastOnce,
      MqttClientPayloadBuilder().addString(jsonEncode(message)).payload!,
    );
  }
}
```

#### Service REST Flutter

```dart
class ChatApiService {
  Future<List<Message>> getHistoricalMessages(
    String conversationId, {
    int page = 1,
    int limit = 50,
  }) async {
    final response = await get('/api/chat/conversations/$conversationId/messages');
    return (response.data as List)
        .map((json) => Message.fromJson(json))
        .toList();
  }
  
  // Note: Pas de POST pour les messages - uniquement pour l'historique
}
```

#### Structure des topics MQTT

```
chat/user/{userId}/messages    - Messages personnels
chat/conversation/{convId}     - Messages de groupe
chat/announcement             - Annonces générales
chat/moderation/{msgId}       - Résultats de modération
chat/typing/{convId}          - Indicateurs de frappe
```

### 7. Module Go Chat Service

Le module Go gère :

1. **Réception MQTT**
   - Écoute les topics de chat
   - Parse les messages JSON
   - Valide le format

2. **Modération**
   - Analyse du contenu
   - Application des règles configurables
   - Filtrage des mots interdits
   - Détection de spam
   - Notification des résultats

3. **Synchronisation base de données**
   - Enregistrement des messages en base
   - Création des notifications
   - Mise à jour des statuts de livraison
   - Gestion des acquittements

**Note importante** : Le module Go n'a aucune interaction avec l'API REST. Il est uniquement connecté au broker MQTT pour recevoir les messages et à la base de données pour les stocker.

4. **Configuration par application**
   ```yaml
   applications:
     geosector:
       moderator_enabled: true
       bad_words: ["liste", "des", "mots"]
       flood_limit: 5
       spam_rules:
         url_limit: 2
         repetition_threshold: 0.8
     resalice:
       moderator_enabled: false
       # Configuration différente
   ```

### 8. Stockage des fichiers

Le système supportera le téléchargement et le partage de fichiers :

1. **Côté serveur** : Stockage dans un répertoire sécurisé avec restriction d'accès
2. **Côté client** : Mise en cache des fichiers pour éviter des téléchargements redondants
3. **Types supportés** : Images, documents, autres fichiers selon configuration

## Cas d'utilisation spécifiques

### 1. Geosector

- **Utilisateurs authentifiés uniquement**
- **Groupes par équipe** avec administrateurs pour les communications internes
- **Modération active** avec filtrage de contenu
- **Historique complet** des conversations
- **Intégration avec la structure existante** des amicales et équipes
- **Annonces et broadcasts**:
  - Super admin → tous les admins d'entités
  - Admin d'entité → tous les utilisateurs de son entité
  - Communications descendantes sans possibilité de réponse
  - Statistiques de lecture des annonces importantes
  - **Ciblage flexible des destinataires** :
    - Par entité (toutes ou une spécifique)
    - Par rôle (tous, membres, administrateurs)
    - Combinaison entité + rôle (ex: admins de l'entité 5)
    - Sélection via le widget `AnnouncementTargetSelector`

### 2. Resalice

- **Chats initiés par des anonymes**
- **Conversation one-to-one uniquement** entre professionnel et client/prospect
- **Pas de modération active** par défaut
- **Conversion client** : Processus pour transformer un utilisateur anonyme en client référencé
- **Conservation des historiques** après conversion
- **Interface professionnelle** adaptée aux échanges client/professionnel
- **Pas de fonctionnalité d'annonce** - uniquement des conversations directes

## Adaptabilité et extensibilité

### 1. Options de personnalisation

- **Thèmes** : Adaptation aux couleurs et styles de l'application
- **Fonctionnalités** : Activation/désactivation de certaines fonctionnalités
- **Comportements** : Configuration des notifications, comportement hors ligne, etc.
- **Modération** : Configuration par application

### 2. Extensions possibles

- **Chatbot** : Possibilité d'intégrer des réponses automatiques
- **Transfert** : Transfert de conversations entre professionnels
- **Intégration CRM** : Liaison avec des systèmes CRM pour le suivi client
- **Analyse** : Statistiques sur les conversations, temps de réponse, etc.
- **Audio/Vidéo** : Support des messages vocaux et vidéo

## Étapes d'implémentation suggérées

1. **Phase 1 : Infrastructure de base** (4-5 semaines)
   - Installation et configuration du broker MQTT
   - Développement du module Go Chat Service
   - Modèles de données et adaptateurs Hive
   - Configuration de l'API backend

2. **Phase 2 : Fonctionnalités principales** (4-5 semaines)
   - Widgets de base pour affichage/envoi de messages
   - Gestion des notifications MQTT
   - Système de modération
   - Structure de base pour les annonces et broadcasts

3. **Phase 3 : Fonctionnalités avancées** (3-4 semaines)
   - Gestion hors ligne et synchronisation
   - Support des fichiers et images
   - Indicateurs de lecture et d'écriture
   - Système de ciblage d'audience pour les annonces

4. **Phase 4 : Cas spécifiques** (3-4 semaines)
   - Support des conversations anonymes (Resalice)
   - Groupes et permissions avancées (Geosector)
   - Statistiques de lecture des annonces
   - Interface administrateur pour les annonces globales
   - Intégration web complète

Le temps total d'implémentation pour Geosector est estimé à 12-15 semaines pour un développeur expérimenté en Flutter, PHP et Go. L'adaptation ultérieure à Resalice devrait prendre environ 3-4 semaines supplémentaires grâce à la conception modulaire du système.

## Conclusion

Cette solution de chat personnalisée offre un équilibre entre robustesse et simplicité d'intégration. Elle répond aux besoins spécifiques de vos applications tout en restant suffisamment flexible pour s'adapter à d'autres contextes.

Le système prend en charge non seulement les conversations classiques (one-to-one, groupes) mais aussi les communications de type annonce/broadcast où un administrateur peut communiquer des informations importantes à des groupes d'utilisateurs définis par rôle ou entité, avec ou sans possibilité de réponse.

### Points clés de l'architecture

1. **Séparation des flux** :
   - **Temps réel** : Via MQTT pour l'envoi de messages et les notifications
   - **Historique** : Via REST pour la récupération des anciennes conversations

2. **Modération centrée** : Le module Go gère la modération sans interaction avec l'API REST

3. **Auto-hébergement** : 
   - Broker MQTT dans votre container Incus
   - Module Go dédié pour la gestion des messages
   - Contrôle total de l'infrastructure

4. **Configuration flexible** : Modération et comportement adaptables par application

En développant cette solution en interne, vous gardez un contrôle total sur les fonctionnalités et l'expérience utilisateur, tout en assurant une cohérence avec le reste de vos applications. La conception modulaire et réutilisable permettra également un déploiement efficace sur vos différentes plateformes et applications.
