import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:em2rp/models/maintenance_model.dart'; import 'package:em2rp/models/alert_model.dart'; import 'package:em2rp/models/equipment_model.dart'; import 'package:em2rp/services/equipment_service.dart'; class MaintenanceService { final FirebaseFirestore _firestore = FirebaseFirestore.instance; final EquipmentService _equipmentService = EquipmentService(); // Collection references CollectionReference get _maintenancesCollection => _firestore.collection('maintenances'); CollectionReference get _equipmentCollection => _firestore.collection('equipment'); CollectionReference get _alertsCollection => _firestore.collection('alerts'); // CRUD Operations /// Créer une nouvelle maintenance Future createMaintenance(MaintenanceModel maintenance) async { try { await _maintenancesCollection.doc(maintenance.id).set(maintenance.toMap()); // Mettre à jour les équipements concernés for (String equipmentId in maintenance.equipmentIds) { await _updateEquipmentMaintenanceList(equipmentId, maintenance.id); // Si la maintenance est planifiée dans les 7 prochains jours, créer une alerte if (maintenance.scheduledDate.isBefore(DateTime.now().add(const Duration(days: 7)))) { await _createMaintenanceAlert(equipmentId, maintenance); } } } catch (e) { print('Error creating maintenance: $e'); rethrow; } } /// Mettre à jour une maintenance Future updateMaintenance(String id, Map data) async { try { data['updatedAt'] = Timestamp.fromDate(DateTime.now()); await _maintenancesCollection.doc(id).update(data); } catch (e) { print('Error updating maintenance: $e'); rethrow; } } /// Supprimer une maintenance Future deleteMaintenance(String id) async { try { // Récupérer la maintenance pour connaître les équipements final doc = await _maintenancesCollection.doc(id).get(); if (doc.exists) { final maintenance = MaintenanceModel.fromMap( doc.data() as Map, doc.id, ); // Retirer la maintenance des équipements for (String equipmentId in maintenance.equipmentIds) { await _removeMaintenanceFromEquipment(equipmentId, id); } } await _maintenancesCollection.doc(id).delete(); } catch (e) { print('Error deleting maintenance: $e'); rethrow; } } /// Récupérer une maintenance par ID Future getMaintenanceById(String id) async { try { final doc = await _maintenancesCollection.doc(id).get(); if (doc.exists) { return MaintenanceModel.fromMap(doc.data() as Map, doc.id); } return null; } catch (e) { print('Error getting maintenance: $e'); rethrow; } } /// Récupérer l'historique des maintenances pour un équipement Stream> getMaintenances(String equipmentId) { try { return _maintenancesCollection .where('equipmentIds', arrayContains: equipmentId) .orderBy('scheduledDate', descending: true) .snapshots() .map((snapshot) { return snapshot.docs .map((doc) => MaintenanceModel.fromMap( doc.data() as Map, doc.id, )) .toList(); }); } catch (e) { print('Error streaming maintenances: $e'); rethrow; } } /// Récupérer toutes les maintenances Stream> getAllMaintenances() { try { return _maintenancesCollection .orderBy('scheduledDate', descending: true) .snapshots() .map((snapshot) { return snapshot.docs .map((doc) => MaintenanceModel.fromMap( doc.data() as Map, doc.id, )) .toList(); }); } catch (e) { print('Error streaming all maintenances: $e'); rethrow; } } /// Marquer une maintenance comme complétée Future completeMaintenance(String id, {String? performedBy, double? cost}) async { try { final updateData = { 'completedDate': Timestamp.fromDate(DateTime.now()), 'updatedAt': Timestamp.fromDate(DateTime.now()), }; if (performedBy != null) { updateData['performedBy'] = performedBy; } if (cost != null) { updateData['cost'] = cost; } await updateMaintenance(id, updateData); // Mettre à jour la date de dernière maintenance des équipements final maintenance = await getMaintenanceById(id); if (maintenance != null) { for (String equipmentId in maintenance.equipmentIds) { await _equipmentCollection.doc(equipmentId).update({ 'lastMaintenanceDate': Timestamp.fromDate(DateTime.now()), }); } } } catch (e) { print('Error completing maintenance: $e'); rethrow; } } /// Vérifier les maintenances à venir et créer des alertes Future checkUpcomingMaintenances() async { try { final sevenDaysFromNow = DateTime.now().add(const Duration(days: 7)); // Récupérer les maintenances planifiées dans les 7 prochains jours final maintenancesQuery = await _maintenancesCollection .where('scheduledDate', isLessThanOrEqualTo: Timestamp.fromDate(sevenDaysFromNow)) .where('completedDate', isNull: true) .get(); for (var doc in maintenancesQuery.docs) { final maintenance = MaintenanceModel.fromMap( doc.data() as Map, doc.id, ); for (String equipmentId in maintenance.equipmentIds) { await _createMaintenanceAlert(equipmentId, maintenance); } } } catch (e) { print('Error checking upcoming maintenances: $e'); rethrow; } } /// Créer une alerte de maintenance à venir Future _createMaintenanceAlert(String equipmentId, MaintenanceModel maintenance) async { try { // Vérifier si une alerte existe déjà final existingAlerts = await _alertsCollection .where('equipmentId', isEqualTo: equipmentId) .where('type', isEqualTo: alertTypeToString(AlertType.maintenanceDue)) .where('isRead', isEqualTo: false) .get(); // Vérifier si l'alerte concerne la même maintenance bool alertExists = false; for (var alertDoc in existingAlerts.docs) { final alertData = alertDoc.data() as Map; if (alertData['message']?.contains(maintenance.name) ?? false) { alertExists = true; break; } } if (!alertExists) { // Récupérer l'équipement pour le nom final equipmentDoc = await _equipmentCollection.doc(equipmentId).get(); String equipmentName = equipmentId; if (equipmentDoc.exists) { final equipmentData = equipmentDoc.data() as Map; equipmentName = equipmentData['name'] ?? equipmentId; } final daysUntil = maintenance.scheduledDate.difference(DateTime.now()).inDays; final alert = AlertModel( id: _alertsCollection.doc().id, type: AlertType.maintenanceDue, message: 'Maintenance "${maintenance.name}" prévue dans $daysUntil jour(s) pour $equipmentName', equipmentId: equipmentId, createdAt: DateTime.now(), ); await _alertsCollection.doc(alert.id).set(alert.toMap()); } } catch (e) { print('Error creating maintenance alert: $e'); rethrow; } } /// Mettre à jour la liste des maintenances d'un équipement Future _updateEquipmentMaintenanceList(String equipmentId, String maintenanceId) async { try { final equipmentDoc = await _equipmentCollection.doc(equipmentId).get(); if (equipmentDoc.exists) { final equipment = EquipmentModel.fromMap( equipmentDoc.data() as Map, equipmentDoc.id, ); final updatedMaintenanceIds = List.from(equipment.maintenanceIds); if (!updatedMaintenanceIds.contains(maintenanceId)) { updatedMaintenanceIds.add(maintenanceId); await _equipmentCollection.doc(equipmentId).update({ 'maintenanceIds': updatedMaintenanceIds, }); } } } catch (e) { print('Error updating equipment maintenance list: $e'); rethrow; } } /// Retirer une maintenance de la liste d'un équipement Future _removeMaintenanceFromEquipment(String equipmentId, String maintenanceId) async { try { final equipmentDoc = await _equipmentCollection.doc(equipmentId).get(); if (equipmentDoc.exists) { final equipment = EquipmentModel.fromMap( equipmentDoc.data() as Map, equipmentDoc.id, ); final updatedMaintenanceIds = List.from(equipment.maintenanceIds); updatedMaintenanceIds.remove(maintenanceId); await _equipmentCollection.doc(equipmentId).update({ 'maintenanceIds': updatedMaintenanceIds, }); } } catch (e) { print('Error removing maintenance from equipment: $e'); rethrow; } } }