import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:image/image.dart' as img; import 'package:path_provider/path_provider.dart'; /// Service untuk mengelola data user (profile, foto, password) class UsersService { final FirebaseAuth _auth = FirebaseAuth.instance; final FirebaseFirestore _firestore = FirebaseFirestore.instance; static const String collectionName = 'users'; User? get currentUser => _auth.currentUser; String get userId => currentUser?.uid ?? ''; /// Inisiasi profil saat pertama kali register Future createUserDocument(String uid, String name, String email) async { try { await _firestore.collection(collectionName).doc(uid).set({ 'user_id': uid, 'display_name': name.trim(), 'email': email.trim(), 'created_at': FieldValue.serverTimestamp(), 'updated_at': FieldValue.serverTimestamp(), }); } catch (e) { throw Exception('Gagal inisiasi dokumen user: $e'); } } /// Update nama user di Firebase Auth dan Firestore Future updateName(String name) async { try { await currentUser?.updateDisplayName(name.trim()); await _firestore.collection(collectionName).doc(userId).set( { 'user_id': userId, 'display_name': name.trim(), 'updated_at': FieldValue.serverTimestamp(), }, SetOptions(merge: true), ); await currentUser?.reload(); } catch (e) { throw Exception('Gagal update nama: $e'); } } /// Kompresi gambar ke 800x800px dengan quality 75% Future _compressImage(File imageFile) async { try { final bytes = await imageFile.readAsBytes(); final image = img.decodeImage(bytes); if (image == null) throw Exception('Gagal decode gambar'); final resized = img.copyResize(image, width: 800, height: 800, maintainAspect: true); final compressed = img.encodeJpg(resized, quality: 75); final dir = await getApplicationDocumentsDirectory(); final compressedFile = File('${dir.path}/profile_compressed.jpg'); await compressedFile.writeAsBytes(compressed); return compressedFile; } catch (e) { throw Exception('Gagal kompresi foto: $e'); } } /// Simpan foto profil ke lokal storage dengan kompresi Future saveProfilePhotoLocal(File imageFile) async { try { if (userId.isEmpty) throw Exception('User tidak terautentikasi'); if (!await imageFile.exists()) throw Exception('File gambar tidak ditemukan'); final compressedFile = await _compressImage(imageFile); final appDocDir = await getApplicationDocumentsDirectory(); final photosDir = Directory('${appDocDir.path}/HydroNutrify/photos'); if (!await photosDir.exists()) { await photosDir.create(recursive: true); } final fileName = 'profile_${DateTime.now().millisecondsSinceEpoch}.jpg'; final localPath = '${photosDir.path}/$fileName'; await compressedFile.copy(localPath); await _firestore.collection(collectionName).doc(userId).set({ 'user_id': userId, 'profile_photo_filename': fileName, 'profile_photo_path': localPath, 'updated_at': FieldValue.serverTimestamp(), }, SetOptions(merge: true)); return localPath; } catch (e) { throw Exception('Gagal simpan foto lokal: $e'); } } /// Get path foto profil dari lokal storage Future getProfilePhotoPath() async { try { final profile = await getUserProfile(); if (profile != null) { final filePath = profile['profile_photo_path'] as String?; if (filePath != null && await File(filePath).exists()) { return filePath; } } return null; } catch (e) { return null; } } /// Update password dengan re-authentication Future reauthenticateAndUpdatePassword(String oldPassword, String newPassword) async { try { if (currentUser == null) throw Exception('User tidak ditemukan'); final email = currentUser!.email; if (email == null) throw Exception('Email tidak ditemukan'); final credential = EmailAuthProvider.credential(email: email, password: oldPassword); await currentUser!.reauthenticateWithCredential(credential); await currentUser!.updatePassword(newPassword); } on FirebaseAuthException catch (e) { if (e.code == 'wrong-password') { throw Exception('Password lama salah'); } else if (e.code == 'weak-password') { throw Exception('Password baru terlalu lemah'); } throw Exception('Gagal update password: ${e.message}'); } } /// Get data profile user dari Firestore Future?> getUserProfile() async { try { if (userId.isEmpty) return null; final doc = await _firestore.collection(collectionName).doc(userId).get(); return doc.data(); } catch (e) { return null; } } /// Stream perubahan profile user real-time Stream getUserProfileStream() { if (userId.isEmpty) return Stream.value(null); return _firestore.collection(collectionName).doc(userId).snapshots().handleError((e) { debugPrint('[UsersService] Stream error: $e'); return null; }); } }