execute method

Future<void> execute()

Implementation

Future<void> execute() async {
  _log.info('šŸ”„ Starting migration to the latest configuration format...');

  if (!ConfigService.isInitialized()) {
    _log.error('āŒ Error: Project not initialized. Run "init" first.');
    return;
  }

  final config = ConfigService.loadLenient();
  if (config == null) {
    _log.error(
      'āŒ Error: Could not find or parse flavor_cli.yaml (or legacy .flavor_cli.json).',
    );
    return;
  }

  // Auto-generate flavor_app_names from the existing app_name if not already set
  FlavorConfig effectiveConfig = config;
  if (config.flavorAppNames == null || config.flavorAppNames!.isEmpty) {
    final flavorAppNames = <String, String>{};
    for (final flavor in config.flavors) {
      flavorAppNames[flavor] = flavor == config.productionFlavor
          ? config.appName
          : '${config.appName}-${flavor[0].toUpperCase()}${flavor.substring(1)}';
    }
    effectiveConfig = config.copyWith(flavorAppNames: flavorAppNames);
    _log.info(
      'šŸ“± Generated app names: ${flavorAppNames.entries.map((e) => '${e.key}: "${e.value}"').join(', ')}',
    );
  }

  // 1. Sync values to .env files if they still exist in the config object
  final runtimeService = RuntimeConfigService();
  if (effectiveConfig.flavorValues.isNotEmpty) {
    _log.info('\nšŸ“ Migrating per-flavor field values to .env files:');

    for (final flavor in effectiveConfig.flavors) {
      final values = effectiveConfig.flavorValues[flavor];
      if (values != null && values.isNotEmpty) {
        _log.info('   → flavor: $flavor');
        runtimeService.updateEnvFile(flavor, values);
      }
    }
  }

  // 2. Generate AppConfig.dart and integrate main files
  _log.info('\nšŸš€ Updating app entry points and configuration...');
  runtimeService.generateAppConfig(effectiveConfig);

  if (effectiveConfig.useSeparateMains) {
    for (final flavor in effectiveConfig.flavors) {
      final path = p.join(ConfigService.root, 'lib/main/main_$flavor.dart');
      runtimeService.integrateMainFile(path, effectiveConfig, flavor: flavor);
    }
  } else {
    runtimeService.integrateMainFile(
      p.join(ConfigService.root, 'lib/main.dart'),
      effectiveConfig,
    );
  }

  // 3. Save config (this will automatically remove 'values' from the YAML/JSON output)
  ConfigService.save(effectiveConfig);

  // 4. Ensure dependencies and assets are configured in pubspec.yaml
  DependencyService.ensureEnvDependencies(effectiveConfig, _log);

  // 5. Delete legacy JSON if it exists
  final legacyFile = File(p.join(ConfigService.root, '.flavor_cli.json'));
  if (legacyFile.existsSync()) {
    legacyFile.deleteSync();
    _log.info('šŸ—‘ļø Deleted legacy .flavor_cli.json');
  }

  _log.info('\nāœ… flavor_cli.yaml has been migrated to the latest version!');
  _log.info(
    'šŸ’” Tip: Run "dart run flavor_cli init --from flavor_cli.yaml" now to synchronize your project with the new configuration.',
  );
}