import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:em2rp/models/event_model.dart'; import 'package:em2rp/models/equipment_model.dart'; import 'package:em2rp/services/equipment_status_calculator.dart'; /// Service étendu pour gérer les 4 étapes : Préparation, Chargement, Déchargement, Retour class EventPreparationServiceExtended { final FirebaseFirestore _firestore = FirebaseFirestore.instance; CollectionReference get _eventsCollection => _firestore.collection('events'); CollectionReference get _equipmentCollection => _firestore.collection('equipments'); // === CHARGEMENT (LOADING) === /// Valider un équipement individuel pour le chargement Future validateEquipmentLoading(String eventId, String equipmentId) async { try { final event = await _getEvent(eventId); if (event == null) throw Exception('Event not found'); final updatedEquipment = event.assignedEquipment.map((eq) { if (eq.equipmentId == equipmentId) { return eq.copyWith(isLoaded: true); } return eq; }).toList(); // Vérifier si tous les équipements sont chargés final allLoaded = updatedEquipment.every((eq) => eq.isLoaded); final updateData = { 'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), }; // Si tous sont chargés, mettre à jour le statut if (allLoaded) { updateData['loadingStatus'] = loadingStatusToString(LoadingStatus.completed); } else { updateData['loadingStatus'] = loadingStatusToString(LoadingStatus.inProgress); } await _eventsCollection.doc(eventId).update(updateData); } catch (e) { print('Error validating equipment loading: $e'); rethrow; } } /// Valider tous les équipements pour le chargement Future validateAllLoading(String eventId) async { try { final event = await _getEvent(eventId); if (event == null) throw Exception('Event not found'); final updatedEquipment = event.assignedEquipment.map((eq) { return eq.copyWith(isLoaded: true); }).toList(); await _eventsCollection.doc(eventId).update({ 'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), 'loadingStatus': loadingStatusToString(LoadingStatus.completed), }); // Invalider le cache des statuts d'équipement EquipmentStatusCalculator.invalidateGlobalCache(); } catch (e) { print('Error validating all loading: $e'); rethrow; } } // === DÉCHARGEMENT (UNLOADING) === /// Valider un équipement individuel pour le déchargement Future validateEquipmentUnloading(String eventId, String equipmentId) async { try { final event = await _getEvent(eventId); if (event == null) throw Exception('Event not found'); final updatedEquipment = event.assignedEquipment.map((eq) { if (eq.equipmentId == equipmentId) { return eq.copyWith(isUnloaded: true); } return eq; }).toList(); // Vérifier si tous les équipements sont déchargés final allUnloaded = updatedEquipment.every((eq) => eq.isUnloaded); final updateData = { 'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), }; // Si tous sont déchargés, mettre à jour le statut if (allUnloaded) { updateData['unloadingStatus'] = unloadingStatusToString(UnloadingStatus.completed); } else { updateData['unloadingStatus'] = unloadingStatusToString(UnloadingStatus.inProgress); } await _eventsCollection.doc(eventId).update(updateData); } catch (e) { print('Error validating equipment unloading: $e'); rethrow; } } /// Valider tous les équipements pour le déchargement Future validateAllUnloading(String eventId) async { try { final event = await _getEvent(eventId); if (event == null) throw Exception('Event not found'); final updatedEquipment = event.assignedEquipment.map((eq) { return eq.copyWith(isUnloaded: true); }).toList(); await _eventsCollection.doc(eventId).update({ 'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), 'unloadingStatus': unloadingStatusToString(UnloadingStatus.completed), }); // Invalider le cache des statuts d'équipement EquipmentStatusCalculator.invalidateGlobalCache(); } catch (e) { print('Error validating all unloading: $e'); rethrow; } } // === PRÉPARATION + CHARGEMENT === /// Valider préparation ET chargement en même temps Future validateAllPreparationAndLoading(String eventId) async { try { final event = await _getEvent(eventId); if (event == null) throw Exception('Event not found'); final updatedEquipment = event.assignedEquipment.map((eq) { return eq.copyWith(isPrepared: true, isLoaded: true); }).toList(); await _eventsCollection.doc(eventId).update({ 'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), 'preparationStatus': preparationStatusToString(PreparationStatus.completed), 'loadingStatus': loadingStatusToString(LoadingStatus.completed), }); // Mettre à jour le statut des équipements for (var equipment in event.assignedEquipment) { final doc = await _equipmentCollection.doc(equipment.equipmentId).get(); if (doc.exists) { await _updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.inUse); } } } catch (e) { print('Error validating all preparation and loading: $e'); rethrow; } } // === DÉCHARGEMENT + RETOUR === /// Valider déchargement ET retour en même temps Future validateAllUnloadingAndReturn( String eventId, Map? returnedQuantities, ) async { try { final event = await _getEvent(eventId); if (event == null) throw Exception('Event not found'); final updatedEquipment = event.assignedEquipment.map((eq) { final returnedQty = returnedQuantities?[eq.equipmentId] ?? eq.returnedQuantity ?? eq.quantity; return eq.copyWith( isUnloaded: true, isReturned: true, returnedQuantity: returnedQty, ); }).toList(); await _eventsCollection.doc(eventId).update({ 'assignedEquipment': updatedEquipment.map((e) => e.toMap()).toList(), 'unloadingStatus': unloadingStatusToString(UnloadingStatus.completed), 'returnStatus': returnStatusToString(ReturnStatus.completed), }); // Mettre à jour les statuts et stocks for (var equipment in updatedEquipment) { final equipmentDoc = await _equipmentCollection.doc(equipment.equipmentId).get(); if (equipmentDoc.exists) { final equipmentData = EquipmentModel.fromMap( equipmentDoc.data() as Map, equipmentDoc.id, ); if (!equipmentData.hasQuantity) { await _updateEquipmentStatus(equipment.equipmentId, EquipmentStatus.available); } if (equipmentData.hasQuantity && equipment.returnedQuantity != null) { final currentAvailable = equipmentData.availableQuantity ?? 0; await _equipmentCollection.doc(equipment.equipmentId).update({ 'availableQuantity': currentAvailable + equipment.returnedQuantity!, 'updatedAt': Timestamp.fromDate(DateTime.now()), }); } } } } catch (e) { print('Error validating all unloading and return: $e'); rethrow; } } // === HELPERS === Future _updateEquipmentStatus(String equipmentId, EquipmentStatus status) async { try { final doc = await _equipmentCollection.doc(equipmentId).get(); if (!doc.exists) return; await _equipmentCollection.doc(equipmentId).update({ 'status': equipmentStatusToString(status), 'updatedAt': Timestamp.fromDate(DateTime.now()), }); } catch (e) { print('Error updating equipment status: $e'); } } Future _getEvent(String eventId) async { try { final doc = await _eventsCollection.doc(eventId).get(); if (doc.exists) { return EventModel.fromMap(doc.data() as Map, doc.id); } return null; } catch (e) { print('Error getting event: $e'); rethrow; } } }