import 'package:flutter/foundation.dart'; // debugPrint import 'package:hive_flutter/hive_flutter.dart'; import '../models/sake_item.dart'; class MigrationService { static const String _boxName = 'sake_items'; static const String _backupBoxName = 'sake_items_backup'; /// Runs the migration process with safety backup. /// Should be called after Hive.init and Adapter registration, but before app UI loads. static Future runMigration() async { debugPrint('[Migration] Starting Phase 0 Migration...'); // 1. Open Boxes final box = await Hive.openBox(_boxName); // 2. Backup Strategy try { final backupBox = await Hive.openBox(_backupBoxName); if (backupBox.isEmpty && box.isNotEmpty) { debugPrint('[Migration] detailed backup started...'); // Copy all for (var key in box.keys) { final SakeItem? item = box.get(key); if (item != null) { await backupBox.put(key, item.copyWith()); } } debugPrint('[Migration] Backup completed. ${backupBox.length} items secured.'); } else { debugPrint('[Migration] Backup skipped (Existing backup found or Empty source).'); } // Close backup to ensure flush await backupBox.close(); } catch (e) { debugPrint('[Migration] CRITICAL ERROR during Backup: $e'); // If backup fails, do we abort? // Yes, abort migration to be safe. return; } // 3. Migration (In-Place) int migratedCount = 0; for (var key in box.keys) { final SakeItem? item = box.get(key); if (item != null) { try { // ensureMigrated checks if displayData is null. // If null, it populates it from legacy fields. bool performed = item.ensureMigrated(); if (performed) { await item.save(); // Persist the new structure (DisplayData, etc) migratedCount++; } } catch (e) { debugPrint('[Migration] Error migrating item $key: $e'); } } } if (migratedCount > 0) { debugPrint('[Migration] Successfully migrated $migratedCount items to Schema v2.0.'); } else { debugPrint('[Migration] No items needed migration.'); } } }