import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:async'; import 'api_service.dart'; import 'dart:math'; class AuthService { // Gunakan ApiService untuk request final ApiService _apiService = ApiService(); // Singleton pattern static final AuthService _instance = AuthService._internal(); factory AuthService() { return _instance; } AuthService._internal(); // Fungsi untuk login Future> login({ required String nik, required String password, }) async { try { print('Memulai proses login...'); // Login tidak menggunakan token, jadi kita gunakan http langsung final response = await http.post( Uri.parse('${ApiService.baseUrl}/login'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({ 'nik': nik, 'password': password, }), ); final data = jsonDecode(response.body); print('Response login: $data'); print('Response status code: ${response.statusCode}'); print('Response body raw: ${response.body}'); if (response.statusCode >= 200 && response.statusCode < 300 && (data['status'] == 'success' || data['success'] == true)) { print('Login berhasil'); print('Full response: $data'); print('Full response keys: ${data.keys.toList()}'); // Mencari token di berbagai kemungkinan lokasi dalam respons String? token; // Periksa berbagai kemungkinan kunci token if (data['token'] != null) { token = data['token']; print('Token ditemukan di kunci: token'); } else if (data['access_token'] != null) { token = data['access_token']; print('Token ditemukan di kunci: access_token'); } else if (data['bearer_token'] != null) { token = data['bearer_token']; print('Token ditemukan di kunci: bearer_token'); } else if (data['data'] != null && data['data']['token'] != null) { token = data['data']['token']; print('Token ditemukan di kunci: data.token'); } print('Token ditemukan: ${token != null ? 'Ya' : 'Tidak'}'); // Pastikan token disimpan di SharedPreferences dan ApiService if (token != null) { // Simpan token menggunakan ApiService await _apiService.setToken(token); print('Token berhasil disimpan: ${token.substring(0, min(10, token.length))}...'); } else { print('PERINGATAN: Tidak ada token dalam respons login!'); // Tanggal/waktu lokal sebagai tanda pengenal unik String localIdentifier = DateTime.now().toIso8601String(); await _apiService.setToken('local_token_$localIdentifier'); print('Token lokal dibuat sebagai fallback'); } final prefs = await SharedPreferences.getInstance(); // Navigasi di response JSON berdasarkan struktur Map penggunaData; if (data['pengguna'] != null) { penggunaData = data['pengguna']; } else if (data['user'] != null) { penggunaData = data['user']; } else if (data['data'] != null && data['data']['user'] != null) { penggunaData = data['data']['user']; } else if (data['data'] != null && data['data']['pengguna'] != null) { penggunaData = data['data']['pengguna']; } else { print('PERINGATAN: Struktur respons tidak sesuai yang diharapkan'); print('Membuat data pengguna minimal'); penggunaData = { 'nik': nik, 'id': 0, // Default ID yang akan diganti nanti 'nama': 'User', // Default nama }; } print('Data pengguna dari API: $penggunaData'); // Store user data from API await prefs.setString('nik', penggunaData['nik'] ?? nik); await prefs.setString('nama_ibu', penggunaData['nama'] ?? 'User'); // Simpan user_id sebagai integer untuk digunakan di fitur lain int userId; if (penggunaData['id'] is String) { userId = int.parse(penggunaData['id']); } else if (penggunaData['id'] is int) { userId = penggunaData['id']; } else { print('PERINGATAN: ID tidak ditemukan atau tidak valid, menggunakan 0'); userId = 0; // Nilai default jika tidak ada ID } await prefs.setInt('user_id', userId); print('User ID yang disimpan: $userId'); // Simpan email dan no_telp jika tersedia if (penggunaData['email'] != null) { await prefs.setString('email', penggunaData['email']); print('Email saved: ${penggunaData['email']}'); } if (penggunaData['no_telp'] != null) { await prefs.setString('no_telp', penggunaData['no_telp']); print('Phone saved: ${penggunaData['no_telp']}'); } else if (penggunaData['telepon'] != null) { await prefs.setString('no_telp', penggunaData['telepon']); print('Phone saved (from telepon field): ${penggunaData['telepon']}'); } if (penggunaData['alamat'] != null) { await prefs.setString('alamat', penggunaData['alamat']); } if (penggunaData['usia'] != null) { await prefs.setInt('usia', penggunaData['usia']); } // Verifikasi data tersimpan final verifyUserId = prefs.getInt('user_id'); final verifyEmail = prefs.getString('email'); final verifyPhone = prefs.getString('no_telp'); final verifyToken = prefs.getString('token'); print('Verifikasi data tersimpan:'); print('- User ID: $verifyUserId'); print('- Email: $verifyEmail'); print('- Phone: $verifyPhone'); print('- Token tersimpan: ${verifyToken != null ? 'Ya' : 'Tidak'}'); return { 'success': true, 'message': data['message'] ?? 'Login berhasil', 'data': penggunaData, }; } else { print('Login gagal: ${data['message'] ?? 'NIK atau password salah'}'); return { 'success': false, 'message': data['message'] ?? 'NIK atau password salah', }; } } catch (e) { print('Error during login: $e'); return { 'success': false, 'message': 'Terjadi kesalahan: $e', }; } } // Fungsi untuk register Future> register({ required String nik, required String nama, required String alamat, required String noTelp, required String password, String? email, }) async { try { print('Memulai proses pendaftaran...'); // Debug: Tampilkan URL yang digunakan print('API URL: ${ApiService.baseUrl}/register'); // Register tidak menggunakan token, jadi kita gunakan http langsung final response = await http.post( Uri.parse('${ApiService.baseUrl}/register'), headers: {'Content-Type': 'application/json'}, body: jsonEncode({ 'nik': nik, 'nama': nama, 'alamat': alamat, 'no_telp': noTelp, 'password': password, 'email': email, 'role': 'parent', // Default role }), ); // Debug: Tampilkan status code dan response body print('Status Code: ${response.statusCode}'); print('Response headers: ${response.headers}'); print('Response body preview: ${response.body.substring(0, min(200, response.body.length))}...'); // Cek apakah response berupa JSON atau HTML if (response.body.trim().startsWith('{') || response.body.trim().startsWith('[')) { // Response adalah JSON final data = jsonDecode(response.body); if (response.statusCode == 200 || response.statusCode == 201) { print('Pendaftaran berhasil'); // Simpan data pendaftaran ke SharedPreferences final prefs = await SharedPreferences.getInstance(); // Save registration data await prefs.setString('nik', nik); await prefs.setString('nama_ibu', nama); await prefs.setString('alamat', alamat); await prefs.setString('no_telp', noTelp); if (email != null && email.isNotEmpty) { await prefs.setString('email', email); print('Email saved from registration: $email'); } // Jika ada ID pengguna di respons, simpan juga if (data['id'] != null) { await prefs.setInt('user_id', data['id']); } else if (data['user_id'] != null) { await prefs.setInt('user_id', data['user_id']); } else if (data['pengguna'] != null && data['pengguna']['id'] != null) { await prefs.setInt('user_id', data['pengguna']['id']); } print('Registration data saved to SharedPreferences:'); print('NIK: $nik'); print('Nama: $nama'); print('No Telp: $noTelp'); print('Email: $email'); return { 'success': true, 'message': data['message'] ?? 'Pendaftaran berhasil', }; } else { return { 'success': false, 'message': data['message'] ?? 'Pendaftaran gagal', 'errors': data['errors'], 'statusCode': response.statusCode }; } } else { // Response bukan JSON (kemungkinan HTML error page) return { 'success': false, 'message': 'Server mengembalikan format yang tidak valid (bukan JSON)', 'statusCode': response.statusCode, 'rawResponse': response.body.length > 100 ? '${response.body.substring(0, 100)}...' : response.body }; } } catch (e) { print('Error during registration: $e'); return { 'success': false, 'message': 'Terjadi kesalahan: $e', }; } } // Fungsi untuk mendapatkan data user yang sedang login Future> getCurrentUser() async { try { final prefs = await SharedPreferences.getInstance(); final nik = prefs.getString('nik'); final userId = prefs.getInt('user_id'); if (nik == null) { return { 'success': false, 'message': 'User belum login', }; } // Baca data lokal terlebih dahulu final localUserData = { 'nik': nik, 'id': userId, 'nama': prefs.getString('nama_ibu') ?? 'User', 'alamat': prefs.getString('alamat') ?? '', 'usia': prefs.getInt('usia') ?? 0, 'email': prefs.getString('email') ?? '', 'no_telp': prefs.getString('no_telp') ?? '', }; print('Local data from SharedPreferences:'); print('Email: ${localUserData['email']}'); print('Phone: ${localUserData['no_telp']}'); try { // Gunakan endpoint yang benar (user, user/profile, atau me) print('Getting user data with token authentication'); // Coba beberapa endpoint yang mungkin ada di Laravel API Map data = {}; bool apiSuccess = false; try { data = await _apiService.get('user'); apiSuccess = true; } catch (e) { print('Endpoint "user" failed: $e'); try { data = await _apiService.get('me'); apiSuccess = true; } catch (e) { print('Endpoint "me" failed: $e'); try { data = await _apiService.get('user/profile'); apiSuccess = true; } catch (e) { print('Endpoint "user/profile" failed: $e'); } } } if (!apiSuccess || data.isEmpty) { print('No API endpoint worked, using local data'); // Jika API tidak mengembalikan data, gunakan data lokal return { 'success': true, 'message': 'Menggunakan data lokal', 'data': localUserData }; } // Debug: Check response structure print('API response structure for getCurrentUser:'); print('Keys: ${data.keys.toList()}'); // Berdasarkan struktur response API Map userData = data; if (data['user'] != null) { userData = data['user']; } else if (data['pengguna'] != null) { userData = data['pengguna']; } else if (data['data'] != null) { userData = data['data']; } // Gabungkan data API dengan data lokal jika ada field yang kosong di API if (userData['email'] == null && localUserData['email'] != null && localUserData['email'] != '') { userData['email'] = localUserData['email']; } if ((userData['no_telp'] == null && userData['telepon'] == null) && localUserData['no_telp'] != null && localUserData['no_telp'] != '') { userData['no_telp'] = localUserData['no_telp']; } return { 'success': true, 'data': userData, }; } catch (e) { print('Error in getCurrentUser: $e'); // Jika API error, gunakan data lokal return { 'success': true, 'message': 'Menggunakan data lokal karena API error: $e', 'data': localUserData }; } } catch (e) { print('Error getting current user: $e'); return { 'success': false, 'message': 'Terjadi kesalahan: $e', }; } } // Fungsi untuk cek status login Future isLoggedIn() async { try { final prefs = await SharedPreferences.getInstance(); final token = prefs.getString('token'); return token != null; } catch (e) { print('Error checking login status: $e'); return false; } } // Fungsi logout Future logout() async { try { try { // Gunakan ApiService untuk logout await _apiService.post('logout', {}); print('User logged out successfully from API'); } catch (e) { print('API logout failed, but will clear local data: $e'); } // Hanya hapus token autentikasi, bukan semua data final prefs = await SharedPreferences.getInstance(); await prefs.remove('token'); return true; } catch (e) { print('Logout error: $e'); // Tetap hapus token meskipun terjadi error try { final prefs = await SharedPreferences.getInstance(); await prefs.remove('token'); } catch (clearError) { print('Error removing token: $clearError'); } return true; } } }