import 'dart:convert'; import 'package:get/get.dart'; import 'package:http/http.dart' as http; import 'package:logger/logger.dart'; import 'package:marco/controller/permission_controller.dart'; import 'package:marco/controller/project_controller.dart'; import 'package:marco/helpers/services/api_endpoints.dart'; import 'package:marco/helpers/services/storage/local_storage.dart'; final Logger logger = Logger(); class AuthService { static const String _baseUrl = ApiEndpoints.baseUrl; static const Map _headers = { 'Content-Type': 'application/json', }; static bool isLoggedIn = false; /// Login with email and password static Future?> loginUser(Map data) async { try { final response = await http.post( Uri.parse("$_baseUrl/auth/login-mobile"), headers: _headers, body: jsonEncode(data), ); final responseData = jsonDecode(response.body); if (response.statusCode == 200 && responseData['data'] != null) { await _handleLoginSuccess(responseData['data']); return null; } else if (response.statusCode == 401) { return {"password": "Invalid email or password"}; } else { return {"error": responseData['message'] ?? "Unexpected error occurred"}; } } catch (e) { logger.e("Login error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Refresh JWT token static Future refreshToken() async { final accessToken = await LocalStorage.getJwtToken(); final refreshToken = await LocalStorage.getRefreshToken(); if (accessToken == null || refreshToken == null || accessToken.isEmpty || refreshToken.isEmpty) { logger.w("Missing access/refresh token."); return false; } final requestBody = { "token": accessToken, "refreshToken": refreshToken, }; try { final response = await http.post( Uri.parse("$_baseUrl/auth/refresh-token"), headers: _headers, body: jsonEncode(requestBody), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) { await LocalStorage.setJwtToken(data['data']['token']); await LocalStorage.setRefreshToken(data['data']['refreshToken']); await LocalStorage.setLoggedInUser(true); logger.i("Token refreshed."); return true; } else { logger.w("Refresh token failed: ${data['message']}"); return false; } } catch (e) { logger.e("Token refresh error: $e"); return false; } } /// Forgot password static Future?> forgotPassword(String email) async { try { final response = await http.post( Uri.parse("$_baseUrl/auth/forgot-password"), headers: _headers, body: jsonEncode({"email": email}), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) return null; return {"error": data['message'] ?? "Failed to send reset link."}; } catch (e) { logger.e("Forgot password error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Request demo static Future?> requestDemo(Map demoData) async { try { final response = await http.post( Uri.parse("$_baseUrl/market/inquiry"), headers: _headers, body: jsonEncode(demoData), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) return null; return {"error": data['message'] ?? "Failed to submit demo request."}; } catch (e) { logger.e("Request demo error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Get list of industries static Future>?> getIndustries() async { try { final response = await http.get( Uri.parse("$_baseUrl/market/industries"), headers: _headers, ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) { return List>.from(data['data']); } return null; } catch (e) { logger.e("Get industries error: $e"); return null; } } /// Generate MPIN static Future?> generateMpin({ required String employeeId, required String mpin, }) async { final token = await LocalStorage.getJwtToken(); try { final response = await http.post( Uri.parse("$_baseUrl/auth/generate-mpin"), headers: { ..._headers, if (token != null && token.isNotEmpty) 'Authorization': 'Bearer $token', }, body: jsonEncode({"employeeId": employeeId, "mpin": mpin}), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) return null; return {"error": data['message'] ?? "Failed to generate MPIN."}; } catch (e) { logger.e("Generate MPIN error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Verify MPIN static Future?> verifyMpin({ required String mpin, required String mpinToken, }) async { final employeeInfo = LocalStorage.getEmployeeInfo(); if (employeeInfo == null) return {"error": "Employee info not found."}; final token = await LocalStorage.getJwtToken(); try { final response = await http.post( Uri.parse("$_baseUrl/auth/login-mpin"), headers: { ..._headers, if (token != null && token.isNotEmpty) 'Authorization': 'Bearer $token', }, body: jsonEncode({ "employeeId": employeeInfo.id, "mpin": mpin, "mpinToken": mpinToken, }), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) return null; return {"error": data['message'] ?? "MPIN verification failed."}; } catch (e) { logger.e("Verify MPIN error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Generate OTP static Future?> generateOtp(String email) async { try { final response = await http.post( Uri.parse("$_baseUrl/auth/send-otp"), headers: _headers, body: jsonEncode({"email": email}), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['success'] == true) return null; return {"error": data['message'] ?? "Failed to generate OTP."}; } catch (e) { logger.e("Generate OTP error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Verify OTP and login static Future?> verifyOtp({ required String email, required String otp, }) async { try { final response = await http.post( Uri.parse("$_baseUrl/auth/login-otp"), headers: _headers, body: jsonEncode({"email": email, "otp": otp}), ); final data = jsonDecode(response.body); if (response.statusCode == 200 && data['data'] != null) { await _handleLoginSuccess(data['data']); return null; } return {"error": data['message'] ?? "OTP verification failed."}; } catch (e) { logger.e("Verify OTP error: $e"); return {"error": "Network error. Please check your connection."}; } } /// Handle login success flow static Future _handleLoginSuccess(Map data) async { final jwtToken = data['token']; final refreshToken = data['refreshToken']; final mpinToken = data['mpinToken']; await LocalStorage.setJwtToken(jwtToken); await LocalStorage.setLoggedInUser(true); if (refreshToken != null) await LocalStorage.setRefreshToken(refreshToken); if (mpinToken != null && mpinToken.isNotEmpty) { await LocalStorage.setMpinToken(mpinToken); await LocalStorage.setIsMpin(true); } else { await LocalStorage.setIsMpin(false); await LocalStorage.removeMpinToken(); } final permissionController = Get.put(PermissionController()); await permissionController.loadData(jwtToken); await Get.find().fetchProjects(); isLoggedIn = true; logger.i("Login success initialized."); } }