import 'package:sysfarma_mobile/src/core/network/api_client.dart'; import 'package:sysfarma_mobile/src/core/network/connectivity_service.dart'; import 'package:sysfarma_mobile/src/core/storage/offline_pos_store.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; final pendingSalesSyncServiceProvider = Provider( PendingSalesSyncService.new, ); class PendingSalesSyncResult { const PendingSalesSyncResult({ required this.processed, required this.failed, required this.remaining, }); final int processed; final int failed; final int remaining; } class PendingSalesSyncService { const PendingSalesSyncService(this.ref); final Ref ref; Future syncAll() async { final online = await ref.read(connectivityServiceProvider).isConnected; if (!online) { final remaining = await countPending(); return PendingSalesSyncResult(processed: 0, failed: 0, remaining: remaining); } final store = ref.read(offlinePosStoreProvider); final api = ref.read(apiClientProvider); final pending = await store.readPendingSales(); final remaining = >[]; var processed = 0; var failed = 0; for (final row in pending) { processed++; final payload = Map.from( row['payload'] as Map? ?? const {}, ); final key = row['idempotency_key']?.toString() ?? ''; final attempts = (row['attempts'] as num?)?.toInt() ?? 0; final response = await api.createDocument( payload: payload, idempotencyKey: key.isEmpty ? null : key, ); if (!response.success) { failed++; remaining.add({ ...row, 'attempts': attempts + 1, 'status': 'failed', 'last_error': response.message, }); } } await store.replacePendingSales(remaining); return PendingSalesSyncResult( processed: processed, failed: failed, remaining: remaining.length, ); } Future retryOne(String idempotencyKey) async { final online = await ref.read(connectivityServiceProvider).isConnected; if (!online) return; final store = ref.read(offlinePosStoreProvider); final api = ref.read(apiClientProvider); final pending = await store.readPendingSales(); final row = pending.firstWhere( (e) => '${e['idempotency_key']}' == idempotencyKey, orElse: () => const {}, ); if (row.isEmpty) return; final payload = Map.from( row['payload'] as Map? ?? const {}, ); final attempts = (row['attempts'] as num?)?.toInt() ?? 0; final response = await api.createDocument( payload: payload, idempotencyKey: idempotencyKey, ); if (response.success) { await store.removePendingSale(idempotencyKey); return; } await store.updatePendingSale(idempotencyKey, { ...row, 'attempts': attempts + 1, 'status': 'failed', 'last_error': response.message, }); } Future discardOne(String idempotencyKey) async { await ref.read(offlinePosStoreProvider).removePendingSale(idempotencyKey); } Future countPending() async { final pending = await ref.read(offlinePosStoreProvider).readPendingSales(); return pending.length; } }