verifyEmailCode method

Future<Map<String, dynamic>> verifyEmailCode(
  1. String email,
  2. String code, {
  3. bool testMode = false,
})

Verify email code

Implementation

Future<Map<String, dynamic>> verifyEmailCode(String email, String code, {bool testMode = false}) async {
  try {
    OnairosDebugHelper.log('🔐 Verifying email code for: $email (code: $code, testMode: $testMode)');

    // Test mode mock response - ALWAYS SUCCEEDS, NO API CALL
    if (testMode) {
      OnairosDebugHelper.log('🚀 Test mode: Auto-accepting ANY code, bypassing all verification');
      await Future.delayed(const Duration(milliseconds: 300));

      // Generate mock JWT token
      final mockJwtToken = _generateMockJwtToken();

      // Store JWT token
      await _storage.storeJwtToken(mockJwtToken);
      await _storage.storeValue('email_verification_token', mockJwtToken);
      await _storage.storeValue('email_verification_email', email);

      // Check if this email has been seen before (stored in secure storage)
      final previouslySeenEmails = await _storage.retrieveValue('known_emails') ?? '';
      OnairosDebugHelper.log('🔍 Known emails from storage: "$previouslySeenEmails"');
      final knownEmailList = previouslySeenEmails.split(',').where((e) => e.isNotEmpty).toList();
      OnairosDebugHelper.log('🔍 Known email list: $knownEmailList');
      final isExistingUser = knownEmailList.contains(email);
      OnairosDebugHelper.log('🔍 Checking if "$email" is in list: $isExistingUser');

      // If this is a new user, remember their email for next time
      if (!isExistingUser) {
        knownEmailList.add(email);
        final updatedEmails = knownEmailList.join(',');
        await _storage.storeValue('known_emails', updatedEmails);
        OnairosDebugHelper.log('📝 New user detected: $email - Saved to storage as: "$updatedEmails"');
      } else {
        OnairosDebugHelper.log('👤 Existing user detected: $email - Skipping onboarding');
      }

      // Mock connected platforms for existing users
      List<String> connectedPlatforms = [];
      if (isExistingUser) {
        // In test mode, show mock platforms for existing users
        connectedPlatforms = ['Instagram', 'YouTube', 'Reddit'];
      }

      OnairosDebugHelper.log('✅ Test mode: Auto-verified with ANY code (${isExistingUser ? "existing" : "new"} user)');
      return {
        'success': true,
        'message': 'Email verification successful (test mode - no validation)',
        'existingUser': isExistingUser,
        'connectedPlatforms': connectedPlatforms, // For existing users
        'jwtToken': mockJwtToken,
        'testMode': true,
      };
    }

    // Live mode: Make authenticated API request
    final response = await _apiKeyService.authenticatedPost(
      'email/verification',
      body: {
        'email': email,
        'code': code,
        'action': 'verify',
      },
    );

    // Store JWT token from response
    if (response['success'] == true && response['jwtToken'] != null) {
      final jwtToken = response['jwtToken'] as String;
      await _storage.storeJwtToken(jwtToken);
      await _storage.storeValue('email_verification_token', jwtToken);
      await _storage.storeValue('email_verification_email', email);
      await _storage.storeValue('email_verification_timestamp', DateTime.now().toIso8601String());

      // Store user type for flow routing
      await _storage.storeValue('user_type', response['existingUser'] == true ? 'existing' : 'new');

      // CRITICAL: Also update native iOS Keychain so iOS app can use it for backend sync
      // This ensures the iOS app uses the correct JWT token for LLM data attribution
      print('🔑 [EMAIL-VERIFY] Attempting to save JWT token to native iOS Keychain...');
      print('🔑 [EMAIL-VERIFY] JWT token length: ${jwtToken.length}');
      print('🔑 [EMAIL-VERIFY] JWT token preview: ${jwtToken.substring(0, jwtToken.length > 30 ? 30 : jwtToken.length)}...');
      try {
        const platform = MethodChannel('com.onairos.oboe/connectors');
        print('🔑 [EMAIL-VERIFY] Calling native setJWTToken method...');
        final saved = await platform.invokeMethod<bool>('setJWTToken', {'token': jwtToken});
        print('🔑 [EMAIL-VERIFY] Native setJWTToken returned: $saved');
        if (saved == true) {
          OnairosDebugHelper.log('✅ JWT token saved to native iOS Keychain for backend sync');
          print('✅ [EMAIL-VERIFY] JWT token saved to native iOS Keychain for backend sync');
        } else {
          OnairosDebugHelper.log('⚠️ Failed to save JWT token to native iOS Keychain (returned false)');
          print('⚠️ [EMAIL-VERIFY] Failed to save JWT token to native iOS Keychain (returned false)');
        }
      } on PlatformException catch (e) {
        OnairosDebugHelper.log('⚠️ PlatformException saving JWT to native iOS: ${e.message}');
        print('⚠️ [EMAIL-VERIFY] PlatformException saving JWT to native iOS: ${e.message}');
        print('⚠️ [EMAIL-VERIFY] Error code: ${e.code}, details: ${e.details}');
        // Don't fail the whole flow if native save fails
      } catch (e) {
        OnairosDebugHelper.log('⚠️ Error saving JWT to native iOS: $e');
        print('⚠️ [EMAIL-VERIFY] Error saving JWT to native iOS: $e');
        print('⚠️ [EMAIL-VERIFY] Error type: ${e.runtimeType}');
        // Don't fail the whole flow if native save fails
      }
    }

    OnairosDebugHelper.log('✅ Email verification completed successfully');
    return response;

  } catch (e) {
    OnairosDebugHelper.log('❌ Error verifying email code: $e');
    return {
      'success': false,
      'message': 'Invalid verification code. Please try again.',
      'error': e.toString(),
    };
  }
}