import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'dart:developer' as dev; import 'package:http/http.dart' as http; import '../Provider/utils_singleton.dart'; class RideSocketServiceManager { static const _chan = MethodChannel('com.camelsoft.wanisdriver/RidePubNubService'); // ✅ ADD: Prevent rapid operations static bool _isOperationInProgress = false; static DateTime? _lastOperation; static const Duration _minOperationInterval = Duration(milliseconds: 2000); // ✅ MAKE THIS STATIC static Future getPubNubAuthToken() async { try { final response = await http.post( Uri.parse('https://server.wanis.io/api/auth/pubnub-token'), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ${utils.token}', // Your existing JWT token }, ); if (response.statusCode == 200) { final data = jsonDecode(response.body); if (data['success'] == true) { dev.log('✅ PubNub auth token received: ${data['authToken']}'); return data['authToken']; // This will be the username } else { dev.log('❌ PubNub token request failed: ${data['error'] ?? 'Unknown error'}'); } } else { dev.log('❌ PubNub token request failed with status: ${response.statusCode}'); } return null; } catch (e) { dev.log('❌ Error getting PubNub token: $e'); return null; } } static Future startService({ required String username, required String pubKey, required String subKey, }) async { // ✅ ADD DEBUG: Track what's calling this dev.log('🚨 startService called from: ${StackTrace.current.toString().split('\n')[1]}'); // ✅ PREVENT rapid operations if (_isOperationInProgress) { debugPrint('⏳ Service operation in progress, skipping...'); return; } // ✅ PREVENT operations too close together if (_lastOperation != null && DateTime.now().difference(_lastOperation!) < _minOperationInterval) { debugPrint('⏳ Too soon since last operation, waiting...'); await Future.delayed(_minOperationInterval); } _isOperationInProgress = true; _lastOperation = DateTime.now(); debugPrint('🔔 startService ➜ user=$username pub=${pubKey.substring(0, 4)}… sub=${subKey.substring(0, 4)}…'); try { // Validate inputs if (username.isEmpty || pubKey.isEmpty || subKey.isEmpty) { debugPrint('❌ Invalid parameters provided'); return; } final isRunning = await isServiceRunning(); if (isRunning) { debugPrint('✅ Service already running, skipping start (no update needed)'); return; } else { debugPrint('▶️ Starting new service...'); // ✅ Get auth token from backend final authToken = await getPubNubAuthToken(); dev.log("startService authToken pubnub : $authToken"); if (authToken == null) { dev.log('❌ Failed to get PubNub auth token, cannot start service'); return; } await _chan.invokeMethod('startService', { 'username': username, 'pubKey': pubKey, 'subKey': subKey, 'authKey': authToken, // ✅ FIXED: Use authToken here }); } debugPrint('✅ Service operation completed'); } on PlatformException catch (e) { debugPrint('❌ RidePubNubService error: ${e.code} - ${e.message}'); rethrow; } catch (e) { debugPrint('❌ Unexpected error: $e'); rethrow; } finally { // ✅ Always reset the flag _isOperationInProgress = false; } } static Future stopService() async { // ✅ PREVENT rapid operations if (_isOperationInProgress) { debugPrint('⏳ Service operation in progress, skipping stop...'); return; } _isOperationInProgress = true; _lastOperation = DateTime.now(); debugPrint('🛑 Stopping service...'); try { await _chan.invokeMethod('stopService'); debugPrint('✅ Service stopped'); } on PlatformException catch (e) { debugPrint('❌ RidePubNubService stop error: ${e.code} - ${e.message}'); rethrow; } catch (e) { debugPrint('❌ Unexpected stop error: $e'); rethrow; } finally { _isOperationInProgress = false; } } static Future isServiceRunning() async { try { final result = await _chan.invokeMethod('isServiceRunning'); debugPrint('🔍 Service running: $result'); return result ?? false; } on PlatformException catch (e) { debugPrint('❌ Error checking service status: ${e.code} - ${e.message}'); return false; } catch (e) { debugPrint('❌ Unexpected error checking service: $e'); return false; } } /// Check service status with retry mechanism static Future isServiceRunningWithRetry({int maxRetries = 3}) async { for (int i = 0; i < maxRetries; i++) { try { return await isServiceRunning(); } catch (e) { if (i == maxRetries - 1) rethrow; await Future.delayed(const Duration(milliseconds: 500)); } } return false; } // ✅ NEW: Only use this method when you absolutely need to force restart static Future forceRestart({ required String username, required String pubKey, required String subKey, }) async { debugPrint('🔄 Force restarting service...'); await stopService(); // Wait for service to fully stop await Future.delayed(const Duration(milliseconds: 2000)); // Verify it's stopped final isStillRunning = await isServiceRunning(); if (isStillRunning) { debugPrint('⚠️ Service still running after stop, waiting longer...'); await Future.delayed(const Duration(milliseconds: 3000)); } // ✅ Get auth token from backend final authToken = await getPubNubAuthToken(); dev.log("forceRestart authToken pubnub : $authToken"); if (authToken == null) { dev.log('❌ Failed to get PubNub auth token, cannot restart service'); return; } await _chan.invokeMethod('startService', { 'username': username, 'pubKey': pubKey, 'subKey': subKey, 'authKey': authToken, // ✅ FIXED: Use authToken here }); debugPrint('✅ Force restart completed'); } // ✅ NEW: Reset operation state (for debugging) static void resetOperationState() { _isOperationInProgress = false; _lastOperation = null; debugPrint('🔧 Service operation state reset'); } }