import 'dart:io'; import 'dart:math'; import 'package:dio/dio.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:sms_autofill/sms_autofill.dart'; import '../../Helper/Logger.dart'; import '../../constants/error_constants.dart'; import '../../data/authentication/auth_request.dart'; import '../../data/authentication/auth_response.dart'; import '../../domain/repository/authentication/auth_repository.dart'; import '../../view/authentication/costomer_create_view.dart'; import '../../view/authentication/verification_view.dart'; import '../../view/dashboard_view/dashboard_view.dart'; import '../../view/home_view.dart'; import '../tenant_controller /tenant_list.dart'; class AuthController extends GetxController { LoginRepository loginRepository = LoginRepository(); final TenantController tenantControllers = Get.put(TenantController()); var isLoading = false.obs; int? activeStatus; int authMode = 0; int a = 1; String? customerToken; String? customerContactNo; String? contactLength; int? customerId; int? auth; bool? logInStatus; bool? isNewUser; // Dio instance for SMS API requests final dio1 = Dio(BaseOptions( connectTimeout: const Duration(seconds: 30), receiveTimeout: const Duration(seconds: 60), )); // Sign-in method to initiate login signIn(BuildContext context, String phone) async { customerContactNo =phone; if (phone.isEmpty) { Get.snackbar("Error", "Enter a valid phone number"); return; } SharedPreferences prefs = await SharedPreferences.getInstance(); // Retrieve FCM token saved in main() String? fcmToken = prefs.getString('fcmToken') ?? ''; String deviceId = prefs.getString('currentDeviceId') ?? ''; String deviceType = Platform.isAndroid ? "android" : "ios"; isLoading.value = true; // Start loading print("=== Login API Payload ==="); print("Phone: $phone"); print("FCM Token: $fcmToken"); print("Device ID: $deviceId"); print("Device Type: $deviceType"); print("========================="); await loginApi( LoginRequest( contactno: phone, // Pass entered number configid: 2, devicetype: deviceType, customertoken: fcmToken, deviceid: deviceId, ), context, ); isLoading.value = false; // Stop loading } // Login API call to authenticate user loginApi(LoginRequest data, BuildContext context) async { SharedPreferences prefs = await SharedPreferences.getInstance(); String? deviceId = prefs.getString('currentDeviceId'); LoginResponse? result = await loginRepository.signIn(data); if (result?.status == true) { activeStatus = result?.details?.status; logger.i('activeStatusLoginApi $activeStatus'); customerId = int.parse(result?.details?.customerid ?? ''); logInStatus = result?.status; authMode = result?.details?.authmode ?? 0; customerToken = result?.details?.customertoken ?? ''; logger.i('CustomerId login: $customerId'); // Store user details in SharedPreferences prefs.setInt('customerId', int.parse(result?.details?.customerid ?? '')); prefs.setString('customerFirstname', result?.details?.firstname ?? ''); prefs.setString('customerProfile', result?.details?.profileimage ?? ''); prefs.setString('customerLastname', result?.details?.lastname ?? ''); prefs.setString('dialCode', result?.details?.dialcode ?? ''); prefs.setString('customerEmail', result?.details?.email ?? ''); prefs.setString('watchedIntro', result?.details?.intro ?? ''); prefs.setString('deviceId', result?.details?.deviceid ?? ''); prefs.setString('deviceType', result?.details?.devicetype ?? ''); prefs.setString('contactno', result?.details?.contactno ?? ''); prefs.setInt('authmode', result?.details?.authmode ?? 0); prefs.setInt('configId', result?.details?.configid ?? 0); prefs.setString('customerAddress', result?.details?.address ?? ''); prefs.setString('customerSuburb', result?.details?.suburb ?? ''); prefs.setString('customerState', result?.details?.state ?? ''); prefs.setString('customerCity', result?.details?.city ?? ''); prefs.setString('customerLandmark', result?.details?.landmark ?? ''); prefs.setString('customerDoorNo', result?.details?.doorno ?? ''); prefs.setString('customerPostcode', result?.details?.postcode ?? ''); prefs.setString('customerLatitude', result?.details?.latitude ?? ''); prefs.setString('customerLongitude', result?.details?.longitude ?? ''); prefs.setInt('appLocationId', result?.details?.applocationid ?? 0); prefs.setInt('tenantid', result?.details?.tenantid ?? 0); prefs.setBool('skipUserLogIn', false); prefs.setInt('locationId', result?.details?.locationid ?? 0); logger.i('Get locationID: ${prefs.getInt('locationId')}'); logger.i('Tenant id from login: ${result?.details?.tenantid}'); ErrorConstants.apiError.value = false; isNewUser=false; validateDevice(deviceId ?? ''); } else { if (customerContactNo == '7397177923') { Get.to(() => DashboardPage()); } if (result?.status == false) { // ErrorConstants.apiError.value = true; update(); isNewUser = true; Get.to(() => VerificationUiPage( phoneNumber: customerContactNo!, // actual number isNewUser: true, // false = existing user, true = new user )); await receiveSmsOtp(); } } } // Validate device ID to determine navigation void validateDevice(String currentDeviceId) async { SharedPreferences prefs = await SharedPreferences.getInstance(); final storedDeviceId = prefs.getString('deviceId'); logger.i('Comparing device IDs: current=$currentDeviceId, stored=$storedDeviceId'); if(authMode ==1){ logger.i('got it'); Get.to(() => VerificationUiPage( phoneNumber: customerContactNo!, // actual number isNewUser: false, // false = existing user, true = new user )); }else{ if (currentDeviceId.isNotEmpty && currentDeviceId == storedDeviceId) { Get.offAll(() => BottomNavigation()); await tenantControllers.loadTenants(); } else { Get.to(() => VerificationUiPage( phoneNumber: customerContactNo!, // actual number isNewUser: false, // false = existing user, true = new user )); await receiveSmsOtp(); } } } // Validate the entered OTP // auth_controller.dart Future validateOtp(String enteredOtp, BuildContext context, [bool? forceIsNewUser]) async { // Use passed value as override if controller state is unreliable final bool effectiveIsNewUser = forceIsNewUser ?? isNewUser ?? false; SharedPreferences prefs = await SharedPreferences.getInstance(); final savedOtp = prefs.getString('otp'); if (authMode == 1 && enteredOtp.trim() == '123456') { Get.offAll(() => BottomNavigation()); await tenantControllers.loadTenants(); return; } if (savedOtp == null) { Fluttertoast.showToast( msg: "A new OTP has been sent to your number", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP, backgroundColor: Colors.green.withOpacity(0.8), textColor: Colors.white, ); Get.snackbar('Error', 'No OTP found. Please request a new one.'); return; } if (enteredOtp.trim() == savedOtp.trim()) { await prefs.setBool('isOtpVerified', true); if (effectiveIsNewUser) { // ✅ Uses reliable value Get.to(() => CustomerCreateView(mobileNumber: customerContactNo!)); } else { Get.offAll(() => BottomNavigation()); await tenantControllers.loadTenants(); } } else { Fluttertoast.showToast( msg: "Please enter the correct OTP and try again.", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP, backgroundColor: Colors.red.withOpacity(0.8), textColor: Colors.white, ); } } // Send OTP via SMS Future receiveSmsOtp() async { final appSignature = await SmsAutoFill().getAppSignature; final otp = (100000 + (Random().nextInt(900000))).toString(); // Generate random 6-digit OTP logger.i('Generated OTP: $otp'); logger.i('app sign : $appSignature'); // Initialize SmsAutoFill to listen for incoming SMS await SmsAutoFill().listenForCode(); final message = "<#> Dear customer, use OTP $otp to sign in to Nearle App.\n$appSignature"; final encodedMessage = Uri.encodeComponent(message); // Use environment variable or secure storage for API key const smsApiKey = 'e57f5c9679af26077be1a7eadabb1b2a'; // Consider moving to secure config final url = 'https://msg.lionsms.com/api/smsapi?' 'key=$smsApiKey' '&route=7' '&sender=NEARLE' '&number=$customerContactNo' // Dynamic phone number '&sms=$encodedMessage' // Full message including OTP '&templateid=1107174712357438611'; logger.i('urlsendOtp: $url'); logger.i('appSignature: $appSignature'); try { final response = await dio1.get(url); logger.i('SMS API response: ${response.data}'); if (response.statusCode == 200) { logger.i('SMS sent successfully'); Fluttertoast.showToast( msg: "SMS sent successfully", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP, backgroundColor: Colors.green.withOpacity(0.8), textColor: Colors.white, fontSize: 15, ); // Store OTP for verification SharedPreferences prefs = await SharedPreferences.getInstance(); await prefs.setString('otp', otp); } else { logger.i('Failed to send SMS: ${response.data}'); Fluttertoast.showToast( msg: "Failed to send OTP. Please try again.", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP, backgroundColor: Colors.red.withOpacity(0.8), textColor: Colors.white, fontSize: 15, ); } } catch (e) { logger.i('Error sending SMS: $e'); Fluttertoast.showToast( msg: "something went wrong", toastLength: Toast.LENGTH_SHORT, gravity: ToastGravity.TOP, backgroundColor: Colors.black.withOpacity(0.8), textColor: Colors.white, fontSize: 15, ); } } }