import 'package:penyaluran_app/app/services/supabase_service.dart'; import 'package:penyaluran_app/app/data/models/user_model.dart'; import 'package:penyaluran_app/app/data/models/warga_model.dart'; import 'package:penyaluran_app/app/data/models/petugas_desa_model.dart'; import 'package:penyaluran_app/app/data/models/donatur_model.dart'; import 'package:penyaluran_app/app/data/models/desa_model.dart'; class AuthProvider { final SupabaseService _supabaseService = SupabaseService.to; // Cache untuk menyimpan data pengguna UserData? _cachedUserData; // Metode untuk login Future signIn(String email, String password) async { try { // Step 1: Login final response = await _supabaseService.client.auth.signInWithPassword( email: email, password: password, ); final user = response.user; if (user == null) { print('Login gagal!'); return null; } final userId = user.id; // Step 2: Ambil role dari view `users_with_roles` atau tabel roles String roleName; try { final roleResponse = await _supabaseService.client .from('users_with_roles') .select('role_name') .eq('id', userId) .single(); roleName = roleResponse['role_name']; } catch (e) { print('Error mengambil role dari users_with_roles: $e'); print('Mencoba ambil role dari tabel roles...'); // Fallback ke cara lama jika view users_with_roles tidak tersedia try { // Ambil role_id dari user metadata final roleId = user.userMetadata?['role_id']; if (roleId == null) { print('Tidak ada role_id di user metadata'); return null; } final roleResponse = await _supabaseService.client .from('roles') .select('role_name') .eq('id', roleId) .single(); roleName = roleResponse['role_name']; } catch (e) { print('Error mengambil role dari tabel roles: $e'); return null; } } print('Role: $roleName'); // Step 3: Ambil profil user berdasarkan role Map? profileResponse; dynamic roleData; DesaModel? desa; // Buat BaseUserModel final baseUser = BaseUserModel( id: userId, email: user.email ?? '', roleId: user.userMetadata?['role_id'], roleName: roleName, createdAt: DateTime.parse(user.createdAt), updatedAt: user.updatedAt != null ? DateTime.parse(user.updatedAt!) : null, ); if (roleName == 'warga') { profileResponse = await _supabaseService.client .from('warga') .select('*, desa:desa_id(id, nama, kecamatan, kabupaten, provinsi)') .eq('id', userId) .single(); // Ekstrak data desa jika ada if (profileResponse['desa'] != null) { desa = DesaModel.fromJson(profileResponse['desa']); print('Data Desa: ${desa.nama}'); } roleData = WargaModel.fromJson(profileResponse); print('Data Warga: ${roleData.namaLengkap}'); } else if (roleName == 'petugas_desa') { profileResponse = await _supabaseService.client .from('petugas_desa') .select('*, desa:desa_id(id, nama, kecamatan, kabupaten, provinsi)') .eq('id', userId) .single(); // Ekstrak data desa jika ada if (profileResponse['desa'] != null) { desa = DesaModel.fromJson(profileResponse['desa']); print('Data Desa: ${desa.nama}'); } roleData = PetugasDesaModel.fromJson(profileResponse); print( 'Data Petugas Desa: ${roleData.namaLengkap}, Desa: ${roleData.desa?.nama}'); } else if (roleName == 'donatur') { profileResponse = await _supabaseService.client .from('donatur') .select('*') .eq('id', userId) .single(); roleData = DonaturModel.fromJson(profileResponse); print('Data Donatur: ${roleData.namaLengkap}'); } else { return null; } if (roleData == null) { print('Tidak menemukan data profil untuk role: $roleName'); return null; } // Perbarui baseUser dengan data desa jika ada final updatedBaseUser = BaseUserModel( id: baseUser.id, email: baseUser.email, roleId: baseUser.roleId, roleName: baseUser.roleName, createdAt: baseUser.createdAt, updatedAt: baseUser.updatedAt, desa: desa, // Set desa dari data yang diambil ); // Simpan cache user data final userData = UserData( baseUser: updatedBaseUser, roleData: roleData, ); _cachedUserData = userData; return userData; } catch (e) { print('Error pada signIn: $e'); rethrow; } } // Metode untuk logout Future signOut() async { try { await _supabaseService.signOut(); _cachedUserData = null; // Hapus cache saat logout } catch (e) { rethrow; } } // Metode untuk mendaftarkan donatur (role_id 3) // Implementasi baru yang tidak memerlukan konfirmasi email Future signUpDonatur({ required String email, required String password, required String namaLengkap, required String alamat, required String noHp, String? jenis, }) async { try { print('DEBUG: Memulai proses registrasi donatur dengan email: $email'); // Step 1: Daftarkan user tanpa metadata dulu // Karena mungkin ada masalah dengan kolom role_id custom final response = await _supabaseService.client.auth.signUp( email: email, password: password, ); final user = response.user; if (user == null) { throw Exception('Gagal membuat akun donatur'); } print('DEBUG: User berhasil terdaftar dengan ID: ${user.id}'); try { // Step 2: Buat data donatur di tabel donatur print('DEBUG: Mencoba menyimpan data donatur ke tabel donatur'); final currentTime = DateTime.now().toIso8601String(); // Data untuk tabel donatur final donaturData = { 'id': user.id, 'nama_lengkap': namaLengkap, 'alamat': alamat, 'no_hp': noHp, 'email': email, 'jenis': jenis ?? 'Individu', 'created_at': currentTime, 'updated_at': currentTime, }; // Insert ke tabel donatur print('DEBUG: Inserting data to donatur table'); await _supabaseService.client.from('donatur').insert(donaturData); print('DEBUG: Berhasil menyimpan data donatur'); // Step 3: Coba update role_id user menggunakan service yang lebih aman print('DEBUG: Mencoba mengupdate role_id user'); await _supabaseService.updateUserRole(user.id, 3); } catch (e) { print('ERROR: Gagal menyimpan data donatur: $e'); throw Exception('Gagal menyimpan data donatur. Silakan coba lagi.'); } print( 'DEBUG: Berhasil mendaftarkan donatur: $namaLengkap dengan ID: ${user.id}'); } catch (e) { print('ERROR: Error pada signUpDonatur: $e'); if (e.toString().contains('User already registered')) { throw Exception( 'Email sudah terdaftar. Silakan gunakan email lain atau login dengan email tersebut.'); } else if (e.toString().contains('Database error saving new user')) { throw Exception( 'Terjadi kesalahan saat menyimpan data pengguna. Silakan coba lagi atau hubungi administrator.'); } else if (e.toString().contains('Error sending confirmation mail')) { print('===== PERHATIAN PENGEMBANG ====='); print( 'Error ini terjadi karena Supabase gagal mengirim email konfirmasi.'); print( 'Untuk mengatasi ini, nonaktifkan konfirmasi email di dashboard Supabase:'); print( '1. Buka project Supabase > Authentication > Email Templates > Confirmation'); print('2. Matikan toggle "Enable email confirmations"'); print('=============================='); throw Exception( 'Gagal mengirim email konfirmasi. Mohon hubungi administrator.'); } else { rethrow; } } } // Metode untuk mendapatkan user saat ini Future getCurrentUser({bool skipCache = false}) async { // Jika ada cache dan user masih terautentikasi, gunakan cache kecuali skipCache = true if (!skipCache && _cachedUserData != null && _supabaseService.isAuthenticated) { print('DEBUG: Menggunakan data user dari cache'); return _cachedUserData; } if (_supabaseService.currentUser != null) { try { // Login berhasil, lakukan proses yang sama seperti di signIn // tapi dengan user yang sudah ada final user = _supabaseService.currentUser!; final userId = user.id; // Step 2: Ambil role dari view `users_with_roles` atau tabel roles String roleName; try { final roleResponse = await _supabaseService.client .from('users_with_roles') .select('role_name') .eq('id', userId) .single(); roleName = roleResponse['role_name']; } catch (e) { print('Error mengambil role dari users_with_roles: $e'); print('Mencoba ambil role dari tabel roles...'); // Fallback ke cara lama jika view users_with_roles tidak tersedia try { // Ambil role_id dari user metadata final roleId = user.userMetadata?['role_id']; if (roleId == null) { print('Tidak ada role_id di user metadata'); return null; } final roleResponse = await _supabaseService.client .from('roles') .select('role_name') .eq('id', roleId) .single(); roleName = roleResponse['role_name']; } catch (e) { print('Error mengambil role dari tabel roles: $e'); return null; } } print('Role: $roleName'); // Step 3: Ambil profil user berdasarkan role Map? profileResponse; dynamic roleData; DesaModel? desa; // Buat BaseUserModel final baseUser = BaseUserModel( id: userId, email: user.email ?? '', roleId: user.userMetadata?['role_id'], roleName: roleName ?? '', createdAt: DateTime.parse(user.createdAt), updatedAt: user.updatedAt != null ? DateTime.parse(user.updatedAt!) : null, ); if ((roleName ?? '').toLowerCase() == 'warga') { profileResponse = await _supabaseService.client .from('warga') .select( '*, desa:desa_id(id, nama, kecamatan, kabupaten, provinsi)') .eq('id', userId) .single(); // Ekstrak data desa jika ada if (profileResponse['desa'] != null) { desa = DesaModel.fromJson(profileResponse['desa']); print('Data Desa: ${desa.nama}'); } roleData = WargaModel.fromJson(profileResponse); print('Data Warga: ${roleData.namaLengkap}'); } else if (roleName.toLowerCase() == 'petugas_desa') { profileResponse = await _supabaseService.client .from('petugas_desa') .select( '*, desa:desa_id(id, nama, kecamatan, kabupaten, provinsi)') .eq('id', userId) .single(); // Ekstrak data desa jika ada if (profileResponse['desa'] != null) { desa = DesaModel.fromJson(profileResponse['desa']); print('Data Desa: ${desa.nama}'); } roleData = PetugasDesaModel.fromJson(profileResponse); } else if (roleName.toLowerCase() == 'donatur') { profileResponse = await _supabaseService.client .from('donatur') .select('*') .eq('id', userId) .single(); roleData = DonaturModel.fromJson(profileResponse); } if (roleData == null) { print('Tidak menemukan data profil untuk role: $roleName'); return null; } // Perbarui baseUser dengan data desa jika ada final updatedBaseUser = BaseUserModel( id: baseUser.id, email: baseUser.email, roleId: baseUser.roleId, roleName: baseUser.roleName, createdAt: baseUser.createdAt, updatedAt: baseUser.updatedAt, desa: desa, // Set desa dari data yang diambil ); // Simpan cache user data final userData = UserData( baseUser: updatedBaseUser, roleData: roleData, ); _cachedUserData = userData; return userData; } catch (e) { print('Error pada getCurrentUser: $e'); } } return null; } // Metode untuk memeriksa apakah user sudah login bool isAuthenticated() { return _supabaseService.isAuthenticated; } // Metode untuk mendapatkan data warga Future?> getWargaData() async { return await _supabaseService.getWargaByUserId(); } // // Metode untuk membuat profil donatur // Future createDonaturProfile({ // required String namaLengkap, // String? instansi, // String? jabatan, // String? noHp, // String? alamat, // String? desaId, // }) async { // await _supabaseService.createDonaturProfile( // namaLengkap: namaLengkap, // instansi: instansi, // jabatan: jabatan, // noHp: noHp, // alamat: alamat, // desaId: desaId, // ); // // Invalidasi cache setelah membuat profil baru // _cachedUserData = null; // } // // Metode untuk membuat profil petugas desa // Future createPetugasDesaProfile({ // required String namaLengkap, // String? nip, // String? jabatan, // String? noHp, // String? alamat, // String? desaId, // }) async { // await _supabaseService.createPetugasDesaProfile( // namaLengkap: namaLengkap, // nip: nip, // jabatan: jabatan, // noHp: noHp, // alamat: alamat, // desaId: desaId, // ); // // Invalidasi cache setelah membuat profil baru // _cachedUserData = null; // } // Metode untuk mendapatkan notifikasi pengguna Future>> getUserNotifications( {bool unreadOnly = false}) async { return await _supabaseService.getUserNotifications(unreadOnly: unreadOnly); } // Metode untuk menandai notifikasi sebagai telah dibaca Future markNotificationAsRead(int notificationId) async { await _supabaseService.markNotificationAsRead(notificationId); } // Metode untuk reset password Future resetPasswordForEmail(String email, {String? redirectTo}) async { await _supabaseService.client.auth.resetPasswordForEmail( email, redirectTo: redirectTo, ); } }