import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import '../models/patient_model.dart'; import '../models/device_model.dart'; import '../models/room_model.dart'; import '../models/notification_model.dart'; import '../models/schedule_model.dart'; import '../models/history_model.dart'; import '../models/user_model.dart'; class FirestoreService { final FirebaseFirestore _firestore = FirebaseFirestore.instance; final FirebaseAuth _auth = FirebaseAuth.instance; // ==================== USER MANAGEMENT ==================== Future userExists(String email) async { try { final snapshot = await _firestore .collection('users') .where('email', isEqualTo: email) .limit(1) .get(); return snapshot.docs.isNotEmpty; } catch (e) { return false; } } Future createUser({ required String email, required String password, required String name, required String role, String? deviceId, }) async { final userCredential = await _auth.createUserWithEmailAndPassword( email: email, password: password, ); final uid = userCredential.user!.uid; await _firestore.collection('users').doc(uid).set({ 'email': email, 'name': name, 'role': role, if (deviceId != null) 'device_id': deviceId, // TAMBAH device_id 'created_at': FieldValue.serverTimestamp(), }); await _auth.signOut(); return uid; } Future updateUser({ required String uid, required String name, String? email, String? deviceId, }) async { final updateData = {'name': name}; if (email != null) updateData['email'] = email; if (deviceId != null) updateData['device_id'] = deviceId; // Support update device_id await _firestore.collection('users').doc(uid).update(updateData); } Future deleteUser(String uid) async { await _firestore.collection('users').doc(uid).delete(); } Future deleteUserFromAuth(String email, String password) async { try { // Sign in temporary dengan user yang akan dihapus final userCredential = await _auth.signInWithEmailAndPassword( email: email, password: password, ); // Hapus user dari Authentication await userCredential.user?.delete(); // Sign out await _auth.signOut(); } catch (e) { print('Error deleting user from auth: $e'); // Jika gagal, ignore error (misalnya user sudah tidak ada) } } Future getUserByEmail(String email) async { try { final snapshot = await _firestore .collection('users') .where('email', isEqualTo: email) .limit(1) .get(); return snapshot.docs.isNotEmpty ? snapshot.docs.first : null; } catch (e) { return null; } } Future getUserModelByEmail(String email) async { try { final snapshot = await _firestore .collection('users') .where('email', isEqualTo: email) .limit(1) .get(); return snapshot.docs.isNotEmpty ? UserModel.fromFirestore(snapshot.docs.first) : null; } catch (e) { return null; } } // ==================== DEVICE MANAGEMENT ==================== Future deviceExists(String deviceId) async { try { final doc = await _firestore.collection('devices').doc(deviceId).get(); return doc.exists; } catch (e) { return false; } } Future patientExistsByDevice(String deviceId) async { try { final snapshot = await _firestore .collection('patients') .where('device_id', isEqualTo: deviceId) .limit(1) .get(); return snapshot.docs.isNotEmpty; } catch (e) { return false; } } Stream> getDevicesStream() { return _firestore .collection('devices') .snapshots() .map( (snapshot) => snapshot.docs .map((doc) => DeviceModel.fromFirestore(doc)) .toList(), ); } Future getDeviceById(String deviceId) async { try { final doc = await _firestore.collection('devices').doc(deviceId).get(); return doc.exists ? DeviceModel.fromFirestore(doc) : null; } catch (e) { return null; } } Future createDevice(DeviceModel device) async { await _firestore .collection('devices') .doc(device.idDevices) .set(device.toFirestore()); } Future deleteDevice(String deviceId) async { await _firestore.collection('devices').doc(deviceId).delete(); } // ==================== PATIENT MANAGEMENT ==================== Stream> getPatientsStream() { return _firestore .collection('patients') .snapshots() .map( (snapshot) => snapshot.docs .map((doc) => PatientModel.fromFirestore(doc)) .toList(), ); } Future getPatientById(String patientId) async { try { final doc = await _firestore.collection('patients').doc(patientId).get(); return doc.exists ? PatientModel.fromFirestore(doc) : null; } catch (e) { return null; } } Future getPatientByDeviceId(String deviceId) async { try { final snapshot = await _firestore .collection('patients') .where('device_id', isEqualTo: deviceId) .limit(1) .get(); return snapshot.docs.isNotEmpty ? PatientModel.fromFirestore(snapshot.docs.first) : null; } catch (e) { return null; } } Future createPatient(PatientModel patient) async { await _firestore.collection('patients').add(patient.toFirestore()); } Future updatePatient(String patientId, PatientModel patient) async { await _firestore .collection('patients') .doc(patientId) .update(patient.toFirestore()); } Future deletePatient(String patientId) async { await _firestore.collection('patients').doc(patientId).delete(); } // ==================== ROOM MANAGEMENT ==================== Future roomExists(String roomId) async { try { final doc = await _firestore.collection('rooms').doc(roomId).get(); return doc.exists; } catch (e) { return false; } } Stream> getRoomsStream() { return _firestore .collection('rooms') .snapshots() .map( (snapshot) => snapshot.docs.map((doc) => RoomModel.fromFirestore(doc)).toList(), ); } Future getRoomById(String roomId) async { try { final doc = await _firestore.collection('rooms').doc(roomId).get(); return doc.exists ? RoomModel.fromFirestore(doc) : null; } catch (e) { return null; } } Future createRoom(RoomModel room) async { await _firestore.collection('rooms').doc(room.id).set(room.toFirestore()); } Future deleteRoom(String roomId) async { await _firestore.collection('rooms').doc(roomId).delete(); } // ==================== HISTORY MANAGEMENT ==================== Stream> getDeviceHistoriesStream(String deviceId) { return _firestore .collection('histories') .where('device_id', isEqualTo: deviceId) .snapshots() .map((snapshot) { final histories = snapshot.docs .map((doc) => HistoryModel.fromFirestore(doc)) .toList(); histories.sort((a, b) => b.timestamp.compareTo(a.timestamp)); return histories; }); } Future> getDeviceHistories( String deviceId, { int limit = 100, }) async { try { final snapshot = await _firestore .collection('histories') .where('device_id', isEqualTo: deviceId) .get(); final histories = snapshot.docs .map((doc) => HistoryModel.fromFirestore(doc)) .toList(); histories.sort((a, b) => b.timestamp.compareTo(a.timestamp)); return histories.take(limit).toList(); } catch (e) { return []; } } Future> getDeviceHistoriesInRange( String deviceId, DateTime startDate, DateTime endDate, ) async { try { final snapshot = await _firestore .collection('histories') .where('device_id', isEqualTo: deviceId) .where('timestamp', isGreaterThanOrEqualTo: startDate) .where('timestamp', isLessThanOrEqualTo: endDate) .get(); final histories = snapshot.docs .map((doc) => HistoryModel.fromFirestore(doc)) .toList(); histories.sort((a, b) => b.timestamp.compareTo(a.timestamp)); return histories; } catch (e) { return []; } } Future> getDeviceHistoriesToday(String deviceId) async { final now = DateTime.now(); final startOfDay = DateTime(now.year, now.month, now.day); final endOfDay = DateTime(now.year, now.month, now.day, 23, 59, 59); return getDeviceHistoriesInRange(deviceId, startOfDay, endOfDay); } Future addHistory(HistoryModel history) async { await _firestore.collection('histories').add(history.toFirestore()); } Future deleteOldHistories({int daysToKeep = 30}) async { final cutoffDate = DateTime.now().subtract(Duration(days: daysToKeep)); final snapshot = await _firestore .collection('histories') .where('timestamp', isLessThan: cutoffDate) .get(); final batch = _firestore.batch(); for (var doc in snapshot.docs) { batch.delete(doc.reference); } await batch.commit(); } // BARU: Hapus semua histories berdasarkan device_id Future deleteHistoriesByDevice(String deviceId) async { final snapshot = await _firestore .collection('histories') .where('device_id', isEqualTo: deviceId) .get(); final batch = _firestore.batch(); for (var doc in snapshot.docs) { batch.delete(doc.reference); } await batch.commit(); } // ==================== NOTIFICATION MANAGEMENT ==================== Stream> getNotificationsStream() { return _firestore .collection('notifications') .orderBy('created_at', descending: true) .snapshots() .map( (snapshot) => snapshot.docs .map((doc) => NotificationModel.fromFirestore(doc)) .toList(), ); } Future addNotification(NotificationModel notification) async { await _firestore .collection('notifications') .add(notification.toFirestore()); } Future markNotificationAsRead(String notificationId) async { await _firestore.collection('notifications').doc(notificationId).update({ 'is_read': true, }); } Future deleteNotification(String notificationId) async { await _firestore.collection('notifications').doc(notificationId).delete(); } // BARU: Hapus semua notifications berdasarkan device_id Future deleteNotificationsByDevice(String deviceId) async { final snapshot = await _firestore .collection('notifications') .where('device_id', isEqualTo: deviceId) .get(); final batch = _firestore.batch(); for (var doc in snapshot.docs) { batch.delete(doc.reference); } await batch.commit(); } // ==================== SCHEDULE MANAGEMENT ==================== Stream> getSchedulesStream({ DateTime? date, String? timeOfDay, }) { Query query = _firestore.collection('schedules'); if (date != null) { final startOfDay = DateTime(date.year, date.month, date.day); final endOfDay = DateTime(date.year, date.month, date.day, 23, 59, 59); query = query .where('schedule_date', isGreaterThanOrEqualTo: startOfDay) .where('schedule_date', isLessThanOrEqualTo: endOfDay); } if (timeOfDay != null) { query = query.where('time_of_day', isEqualTo: timeOfDay); } return query.snapshots().map( (snapshot) => snapshot.docs.map((doc) => ScheduleModel.fromFirestore(doc)).toList(), ); } Future addSchedule(ScheduleModel schedule) async { await _firestore.collection('schedules').add(schedule.toFirestore()); } Future updateSchedule(String scheduleId, ScheduleModel schedule) async { await _firestore .collection('schedules') .doc(scheduleId) .update(schedule.toFirestore()); } Future deleteSchedule(String scheduleId) async { await _firestore.collection('schedules').doc(scheduleId).delete(); } // BARU: Hapus semua schedules berdasarkan device_id Future deleteSchedulesByDevice(String deviceId) async { final snapshot = await _firestore .collection('schedules') .where('device_id', isEqualTo: deviceId) .get(); final batch = _firestore.batch(); for (var doc in snapshot.docs) { batch.delete(doc.reference); } await batch.commit(); } }