import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:manager_api_new/api.dart'; import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Models/AssistantResponse.dart'; class AssistantService { final VisitAppContext visitAppContext; /// Nombre maximum de messages conservés dans l'historique envoyé au backend. final int maxHistory; /// Durée d'inactivité après laquelle l'historique est automatiquement vidé. /// null = pas de vidage automatique. final Duration? inactivityTimeout; final List _history = []; Timer? _inactivityTimer; AssistantService({ required this.visitAppContext, this.maxHistory = 10, this.inactivityTimeout = const Duration(minutes: 5), }); Future chat({ required String message, String? configurationId, bool isVoice = false, }) => chatWithAppType(message: message, configurationId: configurationId, isVoice: isVoice); Future chatWithAppType({ required String message, String? configurationId, AppType appType = AppType.Mobile, bool isVoice = false, }) async { _resetInactivityTimer(); final request = AiChatRequest( message: message, instanceId: visitAppContext.instanceId, appType: appType, configurationId: configurationId, language: visitAppContext.language?.toUpperCase() ?? 'FR', history: List.from(_history), isVoice: isVoice, ); final response = await visitAppContext.clientAPI.aiApi!.aiChat(request); if (response == null) { throw Exception('Empty response from assistant'); } debugPrint("AI raw response: reply='${response.reply}' navigation.sectionId='${response.navigation?.sectionId}' navigation.sectionTitle='${response.navigation?.sectionTitle}' navigation.sectionType='${response.navigation?.sectionType}' cards=${response.cards?.length}"); final result = AssistantResponse( reply: response.reply ?? '', cards: response.cards ?.map((c) => AiCard( title: c.title ?? '', subtitle: c.subtitle ?? '', icon: c.icon, )) .toList(), navigation: response.navigation != null ? AssistantNavigationAction( sectionId: response.navigation!.sectionId ?? '', sectionTitle: response.navigation!.sectionTitle ?? '', sectionType: response.navigation!.sectionType ?? '', imageUrl: response.navigation!.imageUrl, ) : null, expectsReply: response.expectsReply ?? true, ); _history.add(AiChatMessage(role: 'user', content: message)); _history.add(AiChatMessage(role: 'assistant', content: result.reply)); // Cap local — inutile de garder plus que maxHistory côté client if (_history.length > maxHistory) { _history.removeRange(0, _history.length - maxHistory); } return result; } void _resetInactivityTimer() { if (inactivityTimeout == null) return; _inactivityTimer?.cancel(); _inactivityTimer = Timer(inactivityTimeout!, () { debugPrint('[AssistantService] Inactivity timeout — clearing history'); clearHistory(); }); } void clearHistory() { _history.clear(); _inactivityTimer?.cancel(); } void dispose() { _inactivityTimer?.cancel(); } }