import 'package:sysfarma_mobile/src/app/widgets/app_loader.dart'; import 'package:sysfarma_mobile/src/app/widgets/app_panel.dart'; import 'package:sysfarma_mobile/src/core/services/pending_sales_sync_service.dart'; import 'package:sysfarma_mobile/src/core/storage/offline_pos_store.dart'; import 'package:sysfarma_mobile/src/core/theme/app_tokens.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class PendingSyncScreen extends ConsumerStatefulWidget { const PendingSyncScreen({super.key}); @override ConsumerState createState() => _PendingSyncScreenState(); } class _PendingSyncScreenState extends ConsumerState { bool _syncing = false; Future _refresh() async { if (!mounted) return; setState(() {}); } Future _syncAll() async { if (_syncing) return; setState(() => _syncing = true); final result = await ref.read(pendingSalesSyncServiceProvider).syncAll(); if (!mounted) return; setState(() => _syncing = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( 'Sync procesadas: ${result.processed}, fallidas: ${result.failed}, pendientes: ${result.remaining}', ), ), ); await _refresh(); } @override Widget build(BuildContext context) { return SafeArea( child: RefreshIndicator( onRefresh: _refresh, child: FutureBuilder>>( future: ref.read(offlinePosStoreProvider).readPendingSales(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const AppLoader(); } final rows = snapshot.data ?? const >[]; return ListView( padding: AppTokens.pagePadding, children: [ AppPanel( title: 'Sincronizacion de ventas', subtitle: 'Pendientes: ${rows.length}', child: Row( children: [ Expanded( child: FilledButton.icon( onPressed: _syncing ? null : _syncAll, icon: _syncing ? const SizedBox( width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.cloud_sync_rounded), label: Text(_syncing ? 'Sincronizando...' : 'Reintentar todo'), ), ), ], ), ), const SizedBox(height: 12), if (rows.isEmpty) const AppPanel( title: 'Sin pendientes', child: Text('No hay ventas pendientes por sincronizar.'), ) else ...rows.map((row) => _PendingCard( row: row, onRetry: () async { final key = '${row['idempotency_key']}'; await ref.read(pendingSalesSyncServiceProvider).retryOne(key); await _refresh(); }, onDiscard: () async { final key = '${row['idempotency_key']}'; await ref.read(pendingSalesSyncServiceProvider).discardOne(key); await _refresh(); }, )), ], ); }, ), ), ); } } class _PendingCard extends StatelessWidget { const _PendingCard({ required this.row, required this.onRetry, required this.onDiscard, }); final Map row; final VoidCallback onRetry; final VoidCallback onDiscard; @override Widget build(BuildContext context) { final attempts = (row['attempts'] as num?)?.toInt() ?? 0; final error = row['last_error']?.toString(); final createdAt = row['created_at']?.toString() ?? '-'; final key = row['idempotency_key']?.toString() ?? '-'; return Padding( padding: const EdgeInsets.only(bottom: 10), child: AppPanel( title: 'Venta pendiente', subtitle: 'Key: $key', child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Intentos: $attempts'), const SizedBox(height: 4), Text('Creada: $createdAt'), if (error != null && error.isNotEmpty) ...[ const SizedBox(height: 4), Text('Error: $error', style: const TextStyle(color: AppTokens.danger)), ], const SizedBox(height: 10), Row( children: [ Expanded( child: OutlinedButton.icon( onPressed: onRetry, icon: const Icon(Icons.refresh_rounded), label: const Text('Reintentar'), ), ), const SizedBox(width: 8), Expanded( child: OutlinedButton.icon( onPressed: onDiscard, icon: const Icon(Icons.delete_outline_rounded), label: const Text('Descartar'), ), ), ], ), ], ), ), ); } }