import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:shared_preferences/shared_preferences.dart'; import 'package:qyuota/config/api_config.dart'; import 'dart:io'; import 'package:flutter/material.dart'; class AuthService { static const String tokenKey = 'auth_token'; static const String userKey = 'user_data'; static final AuthService _instance = AuthService._internal(); factory AuthService() => _instance; AuthService._internal(); Future?> login(String email, String password) async { try { print('Login attempt with: $email'); // Debug log final response = await http.post( Uri.parse(ApiConfig.login), headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: jsonEncode({ 'email': email, 'password': password, }), ); print('Response status: ${response.statusCode}'); print('Response body: ${response.body}'); if (response.statusCode == 200) { final data = jsonDecode(response.body); await _saveAuthData( data['access_token'], data['user'], ); final prefs = await SharedPreferences.getInstance(); await prefs.setString('user_id', data['user']['id'].toString()); return data; } final errorData = jsonDecode(response.body); throw Exception(errorData['message'] ?? errorData['error'] ?? 'Login failed'); } catch (e) { print('Login error details: $e'); if (e is HandshakeException) { throw Exception('Tidak dapat terhubung ke server. Pastikan server berjalan.'); } rethrow; } } Future logout() async { try { final token = await getToken(); if (token != null) { await http.post( Uri.parse(ApiConfig.logout), headers: ApiConfig.authHeaders(token), ); } } catch (e) { print('Logout error: $e'); } finally { await _clearAuthData(); } } Future?> refreshToken() async { try { final token = await getToken(); if (token == null) throw Exception('No token found'); final response = await http.post( Uri.parse(ApiConfig.refresh), headers: ApiConfig.authHeaders(token), ); if (response.statusCode == 200) { final data = jsonDecode(response.body); await _saveAuthData( data['access_token'], data['user'], ); return data; } throw Exception('Token refresh failed'); } catch (e) { print('Refresh token error: $e'); await _clearAuthData(); rethrow; } } Future _saveAuthData( String token, Map userData, ) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString(tokenKey, token); await prefs.setString(userKey, jsonEncode(userData)); } Future _clearAuthData() async { final prefs = await SharedPreferences.getInstance(); await prefs.remove(tokenKey); await prefs.remove(userKey); } Future getToken() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString(tokenKey); } Future getUserId() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('user_id'); } Future?> getUserData() async { final prefs = await SharedPreferences.getInstance(); final userStr = prefs.getString(userKey); if (userStr != null) { return jsonDecode(userStr); } return null; } Future isLoggedIn() async { final token = await getToken(); return token != null; } Future checkSession(BuildContext context) async { final token = await getToken(); if (token == null) { // Jika tidak ada token, arahkan ke halaman login Navigator.of(context).pushNamedAndRemoveUntil('/login', (route) => false); return false; } try { final response = await http.get( Uri.parse(ApiConfig.profile), headers: ApiConfig.authHeaders(token), ); if (response.statusCode == 401) { // Token tidak valid atau expired await _clearAuthData(); Navigator.of(context).pushNamedAndRemoveUntil('/login', (route) => false); return false; } return true; } catch (e) { print('Error checking session: $e'); return false; } } Future changePassword({ required String currentPassword, required String newPassword, required String confirmPassword, }) async { try { final token = await getToken(); if (token == null) { throw Exception('Token tidak ditemukan'); } print('Attempting to change password...'); print('Endpoint: ${ApiConfig.changePassword}'); final response = await http.post( Uri.parse(ApiConfig.changePassword), headers: { 'Authorization': 'Bearer $token', 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: jsonEncode({ 'current_password': currentPassword, 'new_password': newPassword, 'confirm_password': confirmPassword, }), ); print('Response status: ${response.statusCode}'); print('Response body: ${response.body}'); if (response.statusCode == 200) { return; } final data = jsonDecode(response.body); if (data['errors'] != null) { final errors = data['errors'] as Map; final firstError = errors.values.first; if (firstError is List && firstError.isNotEmpty) { throw Exception(firstError[0]); } throw Exception(firstError.toString()); } throw Exception(data['message'] ?? 'Gagal mengubah password'); } catch (e) { print('Change password error: $e'); if (e is SocketException) { throw Exception('Tidak dapat terhubung ke server. Periksa koneksi internet Anda.'); } rethrow; } } }