execute method

Future<AuthTokens> execute(
  1. DeviceInfo deviceInfo, {
  2. required String app,
})

Authenticate device and get tokens

Flow:

  1. Get device feedback code
  2. If device not found: a. Report feedback in native (Android only) b. Retry API call c. If still fails, retry 10 times with 10 second intervals d. If all attempts fail, show device not enrolled screen
  3. Login with code to get tokens

Implementation

Future<AuthTokens> execute(DeviceInfo deviceInfo, {required String app}) async {
  DebugLogger.log('[AuthenticateUseCase] === execute() called ===');
  DebugLogger.log('[AuthenticateUseCase] Device ID: ${deviceInfo.deviceId}');
  DebugLogger.log('[AuthenticateUseCase] Platform Type: ${deviceInfo.platformType}');

  String platformType;
  switch (deviceInfo.platformType) {
    case PlatformType.android:
      platformType = 'android';
      break;
    case PlatformType.ios:
      platformType = 'ios';
      break;
    case PlatformType.macOS:
      platformType = 'macos';
      break;
    case PlatformType.windows:
      platformType = 'windows';
      break;
    case PlatformType.linux:
      platformType = 'linux';

      break;
  }

  // First attempt to get device feedback
  var feedbackResponse = await repository.getDeviceFeedback(
    deviceInfo.deviceId,
    platformType: platformType,
    app: app,
  );

  // If device not found, report feedback and retry (Android only)
  if (feedbackResponse.isDeviceNotFound) {
    DebugLogger.log('[AuthenticateUseCase] ❌ Device not found');

    // Report feedback in native Android (iOS doesn't have this)
    if (deviceInfo.platformType == PlatformType.android) {
      DebugLogger.log('[AuthenticateUseCase] Reporting feedback in native Android');
      try {
        final reported = await HaloAuthPlatform.instance.reportFeedback(
          deviceInfo.deviceId,
        );
        DebugLogger.log('[AuthenticateUseCase] Feedback reported: $reported');
      } catch (e) {
        DebugLogger.log('[AuthenticateUseCase] ⚠️ Failed to report feedback: $e');
      }
    }

    // Retry API call after reporting feedback
    DebugLogger.log('[AuthenticateUseCase] Retrying device feedback after reporting');
    feedbackResponse = await repository.getDeviceFeedback(
      deviceInfo.deviceId,
      platformType: platformType,
      app: app,
    );

    // If still not found, retry 10 times with 10 second intervals
    if (feedbackResponse.isDeviceNotFound) {
      DebugLogger.log(
        '[AuthenticateUseCase] ❌ Device still not found - starting retry loop (10 attempts, 10 sec intervals)',
      );

      bool success = false;
      for (int attempt = 1; attempt <= 10; attempt++) {
        DebugLogger.log('[AuthenticateUseCase] Retry attempt $attempt/10');

        // Wait 10 seconds before retry (except for first retry which already happened)
        if (attempt > 1) {
          DebugLogger.log(
            '[AuthenticateUseCase] Waiting 10 seconds before next attempt...',
          );
          await Future.delayed(const Duration(seconds: 10));
        }

        feedbackResponse = await repository.getDeviceFeedback(
          deviceInfo.deviceId,
          platformType: platformType,
          app: app,
        );

        if (feedbackResponse.isSuccess && feedbackResponse.data != null) {
          DebugLogger.log(
            '[AuthenticateUseCase] ✅ Device feedback received on attempt $attempt',
          );
          success = true;
          break;
        }

        DebugLogger.log(
          '[AuthenticateUseCase] Attempt $attempt failed: ${feedbackResponse.error}',
        );
      }

      // If all attempts failed, show device not enrolled screen
      if (!success) {
        DebugLogger.log(
          '[AuthenticateUseCase] ❌ All retry attempts failed - showing device not enrolled screen',
        );
        await _navigateToDeviceNotEnrolled(deviceInfo.deviceId);

        // Throw exception after showing screen
        throw Exception('Device not found after all retry attempts');
      }
    }
  }

  // Check if we have a valid code
  if (!feedbackResponse.isSuccess || feedbackResponse.data == null) {
    DebugLogger.log('[AuthenticateUseCase] ❌ Failed to get device feedback code');
    throw Exception(
      'Failed to get device feedback code: ${feedbackResponse.error ?? "Unknown error"}',
    );
  }

  // Login with the code
  DebugLogger.log(
    '[AuthenticateUseCase] ✅ Device feedback code received, logging in...',
  );
  final tokens = await repository.loginWithCode(
    feedbackResponse.data!,
    deviceId: deviceInfo.deviceId,
  );
  DebugLogger.log('[AuthenticateUseCase] ✅ Authentication successful');
  DebugLogger.log('[AuthenticateUseCase] Device ID: ${tokens.deviceId}');

  return tokens;
}