import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert'; import '../models/firefly_account.dart'; class AccountMirrorService { static const String _accountsKey = 'mirrored_accounts'; static const String _lastSyncKey = 'accounts_last_sync'; static const String _lastSyncTimeKey = 'accounts_last_sync_time'; /// Simpan semua akun ke local storage untuk offline usage static Future mirrorAccounts(List accounts) async { final prefs = await SharedPreferences.getInstance(); // Konversi akun ke JSON string final accountsJson = accounts.map((account) => account.toJson()).toList(); await prefs.setStringList( _accountsKey, accountsJson.map((json) => jsonEncode(json)).toList()); await prefs.setInt(_lastSyncTimeKey, DateTime.now().millisecondsSinceEpoch); await prefs.setBool( _lastSyncKey, true); // Menandakan bahwa akun pernah di-sync } /// Ambil semua akun yang telah di-mirror dari local storage static Future> getMirroredAccounts() async { final prefs = await SharedPreferences.getInstance(); final accountsJsonList = prefs.getStringList(_accountsKey) ?? []; if (accountsJsonList.isEmpty) { return []; } return accountsJsonList .map((jsonString) => FireflyAccount.fromJson(json.decode(jsonString))) .toList(); } /// Ambil akun berdasarkan tipe (revenue, asset, dll) static Future> getMirroredAccountsByType( String type) async { final allAccounts = await getMirroredAccounts(); return allAccounts.where((account) => account.type == type).toList(); } /// Ambil akun berdasarkan ID static Future getAccountById(String id) async { final allAccounts = await getMirroredAccounts(); return allAccounts.firstWhere( (account) => account.id == id, orElse: () => FireflyAccount(id: '', name: '', type: ''), ); } /// Periksa apakah akun sudah pernah di-mirror static Future hasMirroredAccounts() async { final prefs = await SharedPreferences.getInstance(); return prefs.containsKey(_accountsKey); } /// Ambil waktu terakhir sync static Future getLastSyncTime() async { final prefs = await SharedPreferences.getInstance(); final timestamp = prefs.getInt(_lastSyncTimeKey); return timestamp != null ? DateTime.fromMillisecondsSinceEpoch(timestamp) : null; } /// Ambil status sync terakhir static Future getLastSyncStatus() async { final prefs = await SharedPreferences.getInstance(); return prefs.getBool(_lastSyncKey) ?? false; } /// Hapus semua data mirror (untuk testing atau reset) static Future clearMirror() async { final prefs = await SharedPreferences.getInstance(); await prefs.remove(_accountsKey); await prefs.remove(_lastSyncTimeKey); await prefs.remove(_lastSyncKey); } /// Update mirror dari server dan simpan ke local storage static Future updateMirrorFromServer( List accounts) async { await mirrorAccounts(accounts); } /// Dapatkan akun dengan prioritas: mirror terbaru > empty list static Future> getAccountsWithFallback( Future> Function() serverFetchFunction, ) async { // Coba ambil dari mirror terlebih dahulu final mirroredAccounts = await getMirroredAccounts(); if (mirroredAccounts.isNotEmpty) { return mirroredAccounts; } // Jika mirror kosong, coba ambil dari server dan mirror try { final serverAccounts = await serverFetchFunction(); if (serverAccounts.isNotEmpty) { // Simpan ke mirror jika berhasil ambil dari server await updateMirrorFromServer(serverAccounts); return serverAccounts; } } catch (e) { print('Gagal mengambil akun dari server: $e'); } // Jika semua gagal, kembalikan empty list return []; } /// Format waktu sync untuk display static String formatSyncTime(DateTime? syncTime) { if (syncTime == null) { return 'Belum pernah disinkronisasi'; } final now = DateTime.now(); final difference = now.difference(syncTime); if (difference.inMinutes < 1) { return 'Baru saja'; } else if (difference.inHours < 1) { final minutes = difference.inMinutes; return '$minutes menit yang lalu'; } else if (difference.inDays < 1) { final hours = difference.inHours; return '$hours jam yang lalu'; } else { final days = difference.inDays; return '$days hari yang lalu'; } } /// Sinkronisasi otomatis jika server tersedia static Future autoSyncIfNeeded( Future> Function() serverFetchFunction, ) async { try { final serverAccounts = await serverFetchFunction(); if (serverAccounts.isNotEmpty) { await updateMirrorFromServer(serverAccounts); return true; } } catch (e) { print('Auto sync gagal: $e'); return false; } return false; } }