import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/foundation.dart'; import '../models/post_item.dart'; class FirestoreService { final FirebaseFirestore _firestore = FirebaseFirestore.instance; FirestoreService() { _initSettings(); } void _initSettings() { try { _firestore.settings = const Settings( persistenceEnabled: true, cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED, ); } catch (e) { if (kDebugMode) { debugPrint('Firestore settings initialization error: $e'); } } } /// Stream of posts ordered by creation date descending Stream> getPostsStream(String collectionName) { return _firestore .collection(collectionName) .orderBy('createdDate', descending: true) .snapshots(includeMetadataChanges: true) .map((snapshot) => snapshot.docs.map((doc) => PostItem.fromFirestore(doc)).toList()); } /// Add a new post / issue / idea Future addPost( String collectionName, PostItem item) async { return await _firestore.collection(collectionName).add(item.toFirestore()); } /// Delete a post by ID Future deletePost(String collectionName, String documentId) async { await _firestore.collection(collectionName).doc(documentId).delete(); } /// Send a contact form submission to Firestore Future submitContactMessage({ required String firstName, required String lastName, required String email, String? phone, required String message, String? authorUid, }) async { await _firestore.collection('ContactMessages').add({ 'firstName': firstName, 'lastName': lastName, 'email': email, 'phone': phone ?? '', 'message': message, 'author_uid': authorUid ?? '', 'createdDate': Timestamp.now(), 'status': 'Neu', }); } /// Stream of all contact messages (for admins) Stream>> getContactMessagesStream() { return _firestore .collection('ContactMessages') .orderBy('createdDate', descending: true) .snapshots(); } /// Update the status of a contact message Future updateContactMessageStatus(String docId, String status) async { await _firestore.collection('ContactMessages').doc(docId).update({ 'status': status, 'statusUpdatedAt': FieldValue.serverTimestamp(), }); } /// Delete a contact message Future deleteContactMessage(String docId) async { await _firestore.collection('ContactMessages').doc(docId).delete(); } /// Stream of all registered users Stream>> getUsersStream() { return _firestore.collection('Users').snapshots(); } /// Stream of all admin documents Stream>> getAdminsStream() { return _firestore.collection('Admins').snapshots(); } /// Upsert a registered user profile into Firestore Future syncUserProfile({ required String uid, required String email, String? displayName, String? firstName, String? lastName, bool? emailVerified, bool? isAdmin, }) async { try { final docRef = _firestore.collection('Users').doc(uid); final doc = await docRef.get(); final data = { 'uid': uid, 'email': email.trim().toLowerCase(), 'lastLogin': FieldValue.serverTimestamp(), if (displayName != null && displayName.isNotEmpty) 'displayName': displayName, if (firstName != null && firstName.isNotEmpty) 'firstName': firstName, if (lastName != null && lastName.isNotEmpty) 'lastName': lastName, if (emailVerified != null) 'emailVerified': emailVerified, if (isAdmin != null) 'isAdmin': isAdmin, }; if (!doc.exists) { data['createdAt'] = FieldValue.serverTimestamp(); } await docRef.set(data, SetOptions(merge: true)); } catch (e) { if (kDebugMode) { debugPrint('Error syncing user profile to Firestore: $e'); } } } /// Promote or demote a user to Admin in Firestore Future setAdminRole({ required String uid, required String email, required bool makeAdmin, String? grantedBy, }) async { final cleanEmail = email.trim().toLowerCase(); final adminRef = _firestore.collection('Admins').doc(uid); final userRef = _firestore.collection('Users').doc(uid); if (makeAdmin) { // 1. Add UID to Admins collection await adminRef.set({ 'uid': uid, 'email': cleanEmail, 'grantedAt': FieldValue.serverTimestamp(), 'grantedBy': grantedBy ?? '', }, SetOptions(merge: true)); // 2. Also ensure email doc exists if email is known if (cleanEmail.isNotEmpty) { await _firestore.collection('Admins').doc(cleanEmail).set({ 'uid': uid, 'email': cleanEmail, 'grantedAt': FieldValue.serverTimestamp(), 'grantedBy': grantedBy ?? '', }, SetOptions(merge: true)); } // 3. Mark user document as admin await userRef.set({'isAdmin': true}, SetOptions(merge: true)); } else { // 1. Remove UID from Admins collection await adminRef.delete(); // 2. Remove email from Admins collection if present if (cleanEmail.isNotEmpty) { try { await _firestore.collection('Admins').doc(cleanEmail).delete(); } catch (_) {} } // 3. Update user document await userRef.set({'isAdmin': false}, SetOptions(merge: true)); } } /// Add admin directly by UID or email (e.g. manual entry) Future addAdminDirectly({ required String identifier, required String email, String? grantedBy, }) async { final cleanId = identifier.trim(); final cleanEmail = email.trim().toLowerCase(); await _firestore.collection('Admins').doc(cleanId).set({ 'uid': cleanId, 'email': cleanEmail, 'grantedAt': FieldValue.serverTimestamp(), 'grantedBy': grantedBy ?? '', }, SetOptions(merge: true)); } }