import 'package:supabase_flutter/supabase_flutter.dart' as supabase; import 'package:dio/dio.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/user_model.dart'; import '../core/api_config.dart'; import 'auth_service.dart'; /// Implementasi AuthService menggunakan Supabase class SupabaseAuthService implements AuthService { final supabase.SupabaseClient _client = supabase.Supabase.instance.client; final Dio _dio = Dio(); @override Future login(String email, String password) async { try { final response = await _client.auth.signInWithPassword( email: email, password: password, ); final user = response.user; if (user == null) { throw Exception('Login gagal: User tidak ditemukan'); } // Ambil device_id dari backend String? deviceId; try { final deviceRes = await _dio.get('${ApiConfig.baseUrl}/device/my-device/${user.id}'); if (deviceRes.statusCode == 200) { deviceId = deviceRes.data['device_id']; } } catch (e) { print('Gagal mengambil info device: $e'); // Tidak melempar error agar login tetap sukses meskipun belum ada device } // Simpan device_id ke cache lokal agar auto-login selanjutnya super cepat if (deviceId != null) { final prefs = await SharedPreferences.getInstance(); await prefs.setString('cached_device_id', deviceId); } return UserModel( id: user.id, name: user.userMetadata?['name'] ?? user.email?.split('@').first ?? 'User', email: user.email ?? email, token: response.session?.accessToken ?? '', deviceId: deviceId, ); } on supabase.AuthException catch (e) { if (e.message.contains('Invalid login credentials')) { throw Exception('Email atau password salah.'); } else if (e.message.contains('Email not confirmed')) { throw Exception('Email belum diverifikasi.'); } throw Exception(e.message); } catch (e) { throw Exception('Terjadi kesalahan koneksi atau server.'); } } @override Future register(String name, String email, String password, String claimCode) async { try { final response = await _client.auth.signUp( email: email, password: password, data: {'name': name}, ); final user = response.user; if (user == null) { throw Exception('Registrasi gagal'); } // Klaim device setelah berhasil mendaftar ke Supabase String? deviceId; try { final claimRes = await _dio.post('${ApiConfig.baseUrl}/device/claim', data: { 'claim_code': claimCode, 'user_id': user.id, }); if (claimRes.statusCode == 200) { deviceId = claimRes.data['device']['device_id']; // Simpan device_id ke cache lokal final prefs = await SharedPreferences.getInstance(); await prefs.setString('cached_device_id', deviceId!); } } catch (e) { // Jika gagal klaim String errorMsg = 'Gagal klaim perangkat.'; if (e is DioException && e.response?.data != null) { errorMsg = e.response?.data['message'] ?? errorMsg; } throw Exception('Akun terbuat, tapi $errorMsg'); } return UserModel( id: user.id, name: name, email: email, token: response.session?.accessToken ?? '', deviceId: deviceId, ); } on supabase.AuthException catch (e) { if (e.message.contains('already registered')) { throw Exception('Email sudah terdaftar.'); } else if (e.message.contains('weak')) { throw Exception('Password terlalu lemah.'); } throw Exception(e.message); } catch (e) { throw Exception('Terjadi kesalahan koneksi atau server.'); } } @override Future logout() async { // Hapus sesi Supabase await _client.auth.signOut(); // Hapus cache device_id agar tidak terbawa jika user login pakai akun lain final prefs = await SharedPreferences.getInstance(); await prefs.remove('cached_device_id'); } // Fungsi tambahan untuk memulihkan sesi Future checkSession() async { final session = _client.auth.currentSession; if (session != null) { final user = session.user; // Ambil device_id langsung dari cache lokal (cepat & offline-safe) String? deviceId; try { final prefs = await SharedPreferences.getInstance(); deviceId = prefs.getString('cached_device_id'); } catch (e) { print('Gagal membaca cache device_id: $e'); } return UserModel( id: user.id, name: user.userMetadata?['name'] ?? user.email?.split('@').first ?? 'User', email: user.email ?? '', token: session.accessToken, deviceId: deviceId, ); } return null; } }