import 'dart:convert'; import 'dart:io'; import 'dart:math'; import 'package:Intaleq/constant/api_key.dart'; import 'package:Intaleq/controller/firebase/firbase_messge.dart'; import 'package:Intaleq/views/auth/otp_page.dart'; import 'package:http/http.dart' as http; import 'package:Intaleq/constant/info.dart'; import 'package:Intaleq/controller/functions/add_error.dart'; import 'package:Intaleq/views/auth/login_page.dart'; import 'package:Intaleq/views/auth/sms_verfy_page.dart'; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:Intaleq/constant/box_name.dart'; import 'package:Intaleq/constant/links.dart'; import 'package:Intaleq/controller/functions/crud.dart'; import 'package:Intaleq/main.dart'; import 'package:Intaleq/views/home/map_page_passenger.dart'; import 'package:jwt_decoder/jwt_decoder.dart'; import 'package:location/location.dart'; import 'package:secure_string_operations/secure_string_operations.dart'; import '../../constant/char_map.dart'; import '../../print.dart'; import '../../views/auth/otp_token_page.dart'; import '../functions/encrypt_decrypt.dart'; import '../functions/package_info.dart'; import '../functions/secure_storage.dart'; import '../functions/securty_check.dart'; class LoginController extends GetxController { final formKey = GlobalKey(); final formKeyAdmin = GlobalKey(); TextEditingController emailController = TextEditingController(); TextEditingController phoneController = TextEditingController(); TextEditingController passwordController = TextEditingController(); TextEditingController adminPasswordController = TextEditingController(); TextEditingController adminNameController = TextEditingController(); bool isAgreeTerms = false; bool isloading = false; late int isTest = 1; void changeAgreeTerm() { isAgreeTerms = !isAgreeTerms; update(); } var dev = ''; @override void onInit() async { await getJWT(); // Log.print('box.read(BoxName.isTest): ${box.read(BoxName.isTest)}'); box.write(BoxName.countryCode, 'Syria'); FirebaseMessagesController().getToken(); super.onInit(); } // getAppTester() async { // var res = await CRUD().get( // link: AppLink.getTesterApp, // payload: {'appPlatform': AppInformation.appName}); // if (res != 'failure') { // var d = jsonDecode(res); // isTest = int.parse(d['message'][0]['isTest'].toString()); // box.write(BoxName.isTest, isTest); // update(); // } else { // box.write(BoxName.isTest, '1'); // update(); // return false; // } // } // updateAppTester(String appPlatform) async { // await CRUD().post( // link: AppLink.updateTesterApp, payload: {'appPlatform': appPlatform}); // } void saveAgreementTerms() { box.write(BoxName.agreeTerms, 'agreed'); update(); } void saveCountryCode(String countryCode) { box.write(BoxName.countryCode, countryCode); update(); } Future getJwtWallet() async { try { final random = Random(); // Perform security check randomly if (random.nextBool()) { await SecurityHelper.performSecurityChecks(); } else { await SecurityChecks.isDeviceRootedFromNative(Get.context!); } String fingerPrint = await DeviceHelper.getDeviceFingerprint(); final dev = GetPlatform.isAndroid ? 'android' : 'ios'; var payload = { 'id': box.read(BoxName.passengerID), 'password': AK.passnpassenger, 'aud': '${AK.allowed}$dev', 'fingerPrint': fingerPrint, }; var response = await http.post( Uri.parse(AppLink.loginJwtWalletRider), body: payload, ); // Handle bad responses if (response.statusCode != 200) { _showJwtErrorDialog( "حدث خطأ أثناء الاتصال بالخادم. يرجى المحاولة مرة أخرى."); throw Exception("JWT request failed"); } var data = jsonDecode(response.body); // Validate JWT response structure if (!data.containsKey('jwt') || !data.containsKey('hmac')) { _showJwtErrorDialog("تعذّر التحقق من الأمان. يرجى إعادة المحاولة."); throw Exception("Invalid JWT response format"); } // Save HMAC locally await box.write(BoxName.hmac, data['hmac']); return data['jwt'].toString(); } catch (e) { _showJwtErrorDialog("حدث خلل غير متوقع. يرجى المحاولة مرة أخرى."); rethrow; } } void _showJwtErrorDialog(String message) { if (Get.context == null) return; Get.defaultDialog( title: "خطأ في الاتصال", middleText: message, textConfirm: "إعادة المحاولة", confirmTextColor: Colors.white, onConfirm: () { Get.back(); getJwtWallet(); }, ); } getJWT() async { // print(Pasenger.pasengerpas); // await SecurityHelper.performSecurityChecks(); Log.print('firstTimeLoadKey: ${box.read(BoxName.firstTimeLoadKey)}'); dev = Platform.isAndroid ? 'android' : 'ios'; if (box.read(BoxName.firstTimeLoadKey).toString() != 'false') { var payload = { 'id': box.read(BoxName.passengerID) ?? AK.newId, 'password': AK.passnpassenger, 'aud': '${AK.allowed}$dev', }; // Log.print('payload: ${payload}'); var response0 = await http.post( Uri.parse(AppLink.loginFirstTime), body: payload, ); if (response0.statusCode == 200) { final decodedResponse1 = jsonDecode(response0.body); final jwt = decodedResponse1['jwt']; final refreshToken = decodedResponse1['refresh_token']; box.write(BoxName.jwt, c(jwt)); // Sss.write(BoxName.jwt, jwt); await storage.write(key: BoxName.refreshToken, value: refreshToken); // await AppInitializer().getAIKey(Pasenger.keyOfApp); // await AppInitializer().getAIKey(Pasenger.initializationVector); // await Future.delayed(Duration.zero); await EncryptionHelper.initialize(); await AppInitializer().getKey(); } else {} } else { await EncryptionHelper.initialize(); var payload = { 'id': box.read(BoxName.passengerID), 'password': box.read(BoxName.email), 'aud': '${AK.allowed}$dev', }; // Log.print('payload: ${payload}'); var response1 = await http.post( Uri.parse(AppLink.loginJwtRider), body: payload, ); Log.print('req: ${response1.request}'); Log.print('response: ${response1.body}'); Log.print('payload: ${payload}'); // Log.print('decodedResponse1: ${jsonDecode(response1.body)}'); if (response1.statusCode == 200) { final decodedResponse1 = jsonDecode(response1.body); // Log.print('decodedResponse1: ${decodedResponse1}'); final jwt = decodedResponse1['jwt']; await box.write(BoxName.jwt, c(jwt)); await AppInitializer().getKey(); // final refreshToken = decodedResponse1['refresh_token']; // await storage.write(key: BoxName.refreshToken, value: refreshToken); } } } Future loginUsingCredentials(String passengerID, String email) async { isloading = true; update(); await getJWT(); try { // 1) استعلام تسجيل الدخول final res = await CRUD().get( link: AppLink.loginFromGooglePassenger, payload: { 'email': email, 'id': passengerID, // استخدم المعامل مباشرة 'platform': Platform.isAndroid ? 'android' : 'ios', 'appName': AppInformation.appName, }, ); if (res == 'Failure') { Get.snackbar("User does not exist.".tr, '', backgroundColor: Colors.red); return; } // 2) فك JSON مرة واحدة final decoded = jsonDecode(res); if (decoded is! Map || decoded.isEmpty) return; final status = (decoded['status'] ?? '').toString(); final data = (decoded['data'] as List?)?.firstOrNull as Map? ?? {}; if (status != 'success' || data['verified'].toString() != '1') { // غير مُفعل -> أذهب للتسجيل بالـ SMS Get.offAll(() => PhoneNumberScreen()); return; } // 3) كتابة القيم (خفيفة) box.write(BoxName.isVerified, '1'); box.write(BoxName.email, data['email']); box.write(BoxName.phone, data['phone']); box.write(BoxName.name, data['first_name']); box.write(BoxName.isTest, '1'); box.write(BoxName.package, data['package']); box.write(BoxName.promo, data['promo']); box.write(BoxName.discount, data['discount']); box.write(BoxName.validity, data['validity']); box.write(BoxName.isInstall, data['isInstall'] ?? 'none'); box.write(BoxName.isGiftToken, data['isGiftToken'] ?? 'none'); if (data['inviteCode'] != null) { box.write(BoxName.inviteCode, data['inviteCode'].toString()); } // مهم: تأكد من passengerID في الـ box box.write(BoxName.passengerID, passengerID); // 4) نفّذ عمليات مكلفة بالتوازي: getTokens + fingerprint final results = await Future.wait([ CRUD().get(link: AppLink.getTokens, payload: { 'passengerID': passengerID, // FIX: لا تستخدم box هنا }), DeviceHelper.getDeviceFingerprint(), ]); await box.write(BoxName.firstTimeLoadKey, 'false'); final tokenResp = results[0]; final fingerPrint = (results[1] ?? '').toString(); await storage.write(key: BoxName.fingerPrint, value: fingerPrint); if (email != '962798583052@intaleqapp.com' && tokenResp != 'failure') { final tokenJson = jsonDecode(tokenResp); final serverToken = tokenJson['message']?['token']?.toString() ?? ''; // Log.print('serverToken: ${serverToken}'); final localFcm = (box.read(BoxName.tokenFCM) ?? '').toString(); // Log.print('localFcm: ${localFcm}'); // 5) اختلاف الجهاز -> تحقّق OTP if (serverToken.isNotEmpty && serverToken != localFcm) { final goVerify = await _confirmDeviceChangeDialog(); if (goVerify == true) { await Get.to(() => OtpVerificationPage( phone: data['phone'].toString(), deviceToken: fingerPrint, token: tokenResp.toString(), ptoken: serverToken, )); // بعد العودة من OTP (نجح/فشل)، أخرج من الميثود كي لا يحصل offAll مرتين return; } } } // 6) منطق الدعوة (إن وُجد) ثم الانتقال final invite = box.read(BoxName.inviteCode)?.toString() ?? 'none'; final isInstall = box.read(BoxName.isInstall)?.toString() ?? '0'; if (invite != 'none' && isInstall != '1') { try { await CRUD().post(link: AppLink.updatePassengersInvitation, payload: { "inviteCode": invite, "passengerID": passengerID, }); await Get.defaultDialog( title: 'Invitation Used'.tr, middleText: "Your invite code was successfully applied!".tr, textConfirm: "OK".tr, confirmTextColor: Colors.white, onConfirm: () async { try { await CRUD().post(link: AppLink.addPassengersPromo, payload: { "promoCode": 'I-${(box.read(BoxName.name)).toString().split(' ').first}', "amount": '25', "passengerID": passengerID, "description": 'promo first' }); } catch (e) { addError( e.toString(), 'promo on invitation in login_controller'); } finally { Get.offAll(() => const MapPagePassenger()); } }, ); return; } catch (_) { // حتى لو فشل، كمل للصفحة الرئيسية } } Get.offAll(() => const MapPagePassenger()); } catch (e, st) { addError('$e', 'loginUsingCredentials'); Get.snackbar('Error', e.toString(), backgroundColor: Colors.redAccent); } finally { isloading = false; update(); } } Future _confirmDeviceChangeDialog() { return Get.defaultDialog( barrierDismissible: false, title: 'Device Change Detected'.tr, middleText: 'Please verify your identity'.tr, textConfirm: 'Verify'.tr, confirmTextColor: Colors.white, onConfirm: () => Get.back(result: true), textCancel: 'Cancel'.tr, onCancel: () => Get.back(result: false), ); } void login() async { isloading = true; update(); var res = await CRUD().get(link: AppLink.loginFromGooglePassenger, payload: { 'email': (emailController.text), 'id': passwordController.text, "platform": Platform.isAndroid ? 'android' : 'ios', "appName": AppInformation.appName, }); isloading = false; update(); if (res == 'Failure') { //Failure Get.offAll(() => LoginPage()); isloading = false; update(); // Get.snackbar("User does not exist.".tr, '', backgroundColor: Colors.red); } else { var jsonDecoeded = jsonDecode(res); if (jsonDecoeded.isNotEmpty) { if (jsonDecoeded['status'] == 'success' && jsonDecoeded['data'][0]['verified'].toString() == '1') { // box.write(BoxName.isVerified, '1'); box.write(BoxName.email, jsonDecoeded['data'][0]['email']); box.write(BoxName.name, jsonDecoeded['data'][0]['first_name']); box.write(BoxName.phone, jsonDecoeded['data'][0]['phone']); box.write(BoxName.passengerID, passwordController.text); // var token = await CRUD().get(link: AppLink.getTokens, payload: { // 'passengerID': box.read(BoxName.passengerID).toString() // }); // await updateAppTester(AppInformation.appName); Get.offAll(() => const MapPagePassenger()); } else { // Get.offAll(() => SmsSignupEgypt()); // Get.snackbar(jsonDecoeded['status'], jsonDecoeded['data'], // backgroundColor: Colors.redAccent); isloading = false; update(); } } else { isloading = false; update(); } } } goToMapPage() { if (box.read(BoxName.email) != null) { Get.offAll(() => const MapPagePassenger()); } } final location = Location(); // late PermissionStatus permissionGranted = PermissionStatus.denied; Future getLocationPermission() async { bool serviceEnabled; PermissionStatus permissionGranted; // Check if location services are enabled serviceEnabled = await location.serviceEnabled(); if (!serviceEnabled) { serviceEnabled = await location.requestService(); if (!serviceEnabled) { // Location services are still not enabled, handle the error return; } } // Check if the app has permission to access location permissionGranted = await location.hasPermission(); if (permissionGranted == PermissionStatus.denied) { permissionGranted = await location.requestPermission(); if (permissionGranted != PermissionStatus.granted) { // Location permission is still not granted, handle the error permissionGranted = await location.requestPermission(); return; } } if (permissionGranted.toString() == 'PermissionStatus.granted') { box.write(BoxName.locationPermission, 'true'); } update(); } }