firebaseSetupCommand function

Future<void> firebaseSetupCommand({
  1. required bool full,
  2. required String env,
})

Orchestrates the full Firebase setup flow for a Flutter project.

If full is true, it performs a comprehensive setup including tool checks, login, project creation, and dependency configuration. The env parameter specifies the target environment (e.g., 'dev').

Implementation

Future<void> firebaseSetupCommand({
  required bool full,
  required String env,
}) async {
  final firebase = FirebaseService();
  final flutter = FlutterService();
  final prompt = PromptService();
  final envService = EnvService();
  final feature = FeatureService();

  print('šŸš€ FirePilot: Elite Firebase Setup ($env)\n');

  try {
    /// šŸ”¹ Validate Flutter project
    if (!File('pubspec.yaml').existsSync()) {
      print('āŒ Not a Flutter project');
      print('šŸ‘‰ Run this inside a Flutter project folder');
      return;
    }

    /// šŸ”¹ Check & auto-fix tools
    await _checkAndFixTools();

    /// šŸ”¹ Ask Project ID
    /// šŸ”¹ Ask Project ID with Validation
    String projectId = '';
    while (true) {
      projectId = prompt.ask('Enter Firebase project ID');

      if (projectId.isEmpty) {
        print('āŒ Project ID cannot be empty');
        continue;
      }

      final regExp = RegExp(r'^[a-z][a-z0-9-]{5,29}$');
      if (!regExp.hasMatch(projectId)) {
        print('āŒ Invalid Project ID format');
        print('šŸ‘‰ Must be 6-30 chars, lowercase, numbers, and hyphens (no underscores)');
        print('šŸ‘‰ Must start with a letter');
        continue;
      }
      break;
    }

    /// šŸ”¹ Firebase Login & Account verification
    print('šŸ” Checking Firebase login...');
    final activeAccount = await firebase.login();
    if (activeAccount != null) {
      print('āœ… Active Account: $activeAccount\n');
    }

    /// šŸ”¹ List & Check Projects
    print('\nšŸ“‹ Checking your Firebase projects...');
    final existingProjects = await firebase.listProjects();

    final alreadyExists = existingProjects.contains(projectId);

    if (alreadyExists) {
      print('āŒ Project ID "$projectId" is already taken in your Firebase console.');
      print('šŸ‘‰ Please choose a unique ID for your new project.');
      print('āŒ Setup stopped.');
      return;
    }

    print('šŸ“‹ Found ${existingProjects.length} existing projects.');

    // Suggest similar IDs if any
    final similar = existingProjects.where((p) => p.contains(projectId) || projectId.contains(p)).toList();
    if (similar.isNotEmpty) {
      print('\nšŸ’” Similar projects found in your account:');
      for (var s in similar) {
        print('   - $s');
      }
      final useSimilar = prompt.confirm('Do you want to use one of these instead?');
      if (useSimilar) {
        final index = prompt.select('Select project', similar);
        projectId = similar[index];
        print('āœ… Selected: $projectId');

        // šŸ”„ Re-check if the selected "similar" project exists (it obviously does)
        // Since the user wants to STOP if it exists, selecting a similar existing one might also mean we stop?
        // Actually, if we allow them to select an existing one, and then stop, that's confusing.
        // I'll add a warning that choosing an existing one will also stop if they want only NEW projects.
        // Wait, the user said "if i choose project id ... and someone has taken ... then can i make ... No".
        // They want to make a NEW project.
        print('āŒ Selected project "$projectId" already exists.');
        print('āŒ Setup stopped.');
        return;
      }
    }

    /// šŸ”¹ Create Project (Mandatory for a clean setup)
    final displayName = prompt.ask('Enter Firebase project display name (Optional, press Enter to use ID)');
    final finalDisplayName = displayName.isEmpty ? projectId : displayName;

    print('šŸ“¦ Creating NEW Firebase project "$projectId" ($finalDisplayName)...');

    try {
      await firebase.createProject(projectId, displayName: finalDisplayName);
      print('āœ… Project created successfully');
    } catch (e) {
      print('\nāŒ Project creation failed!');
      print('šŸ‘‰ Error: $e');
      print('\nāš ļø POSSIBLE REASONS:');
      print('   1. ID "$projectId" is already taken GLOBALLY by another user.');
      print('   2. Quota Limit: You have exceeded the max number of projects for your account.');
      print('   3. Billing/Policy: Some accounts require billing to create new projects.\n');
      print('šŸ‘‰ TIP: Check your Firebase Console to delete old test projects.');
      print('āŒ Setup stopped.');
      return;
    }

    /// šŸ”¹ Interactive Platform Selection
    final platforms = ['android', 'ios'];
    print('šŸ–„ļø platform Selection (Android & iOS are default)');
    if (prompt.confirm('Enable Windows support?')) {
      platforms.add('windows');
    }
    if (prompt.confirm('Enable macOS support?')) {
      platforms.add('macos');
    }

    /// šŸ”¹ Interactive Feature Selection
    final selectedFeatures = <String>[];
    if (full) {
      print('\nšŸš€ Feature Selection');
      if (prompt.confirm('Enable Firebase Auth?')) {
        selectedFeatures.add('auth');
      }
      if (prompt.confirm('Enable Cloud Messaging (FCM)?')) {
        selectedFeatures.add('fcm');
      }
    }

    /// šŸ”¹ Configure FlutterFire
    print('\nāš™ļø Configuring FlutterFire for: ${platforms.join(', ')}...');
    await firebase.configure(projectId, platforms: platforms, env: env);

    /// šŸ”¹ Add Dependencies
    print('šŸ“¦ Adding Firebase dependencies...');
    await flutter.addDeps(); // Adds firebase_core

    // Add feature-specific dependencies
    for (final f in selectedFeatures) {
      if (f == 'auth') await flutter.addDep('firebase_auth');
      if (f == 'fcm') await flutter.addDep('firebase_messaging');
    }

    /// šŸ”‘ Setup SHA
    print('šŸ”‘ Setting up SHA...');
    try {
      await firebase.setupSha(projectId);
    } catch (e) {
      print('āš ļø SHA setup failed, skipping...');
    }

    /// šŸ”¹ Create Environment Folder
    print('šŸŒ Setting up environment...');
    envService.create(env);

    /// šŸ”„ Enable selected Features in Console
    if (selectedFeatures.isNotEmpty) {
      print('šŸ”„ Enabling selected features...\n');
      for (final f in selectedFeatures) {
        await feature.enable(f, projectId: projectId);
      }
      print('\nšŸ“¦ Enabled: ${selectedFeatures.join(', ')}');
    } else if (full) {
      print('ā„¹ļø No additional features selected');
    } else {
      print('ā„¹ļø Skipping feature setup (use --full to enable selection)');
    }

    print('\nšŸŽ‰ Firebase setup completed successfully for [$env]');
  } catch (e) {
    print('\nāŒ Setup failed!');
    print('Error: $e');
  }
}