import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:aves/model/source/collection_source.dart'; import 'package:aves/remote/collection_source_remote_ext.dart'; // appendRemoteEntriesFromDb() import 'package:aves/remote/remote_controller.dart'; import 'package:aves/remote/remote_settings.dart'; import 'package:aves/remote/remote_http.dart'; import 'package:aves/remote/remote_sync_bus.dart'; import 'remote_origin.dart'; class RemoteSettingsDialog { static Future show(BuildContext context) async { final s = await RemoteSettings.load(); final formKey = GlobalKey(); // stato locale della dialog (serve StateSetter) bool enabled = s.enabled; final baseUrlC = TextEditingController(text: s.baseUrl); final indexC = TextEditingController(text: s.indexPath); final emailC = TextEditingController(text: s.email); final pwC = TextEditingController(text: s.password); String? validateBaseUrl(String? v) { final txt = (v ?? '').trim(); if (txt.isEmpty) return 'Obbligatorio'; final uri = Uri.tryParse(txt); if (uri == null || !(uri.hasScheme && (uri.scheme == 'http' || uri.scheme == 'https'))) { return 'URL non valida (deve iniziare con http/https)'; } return null; } String? validateIndex(String? v) { final txt = (v ?? '').trim(); if (txt.isEmpty) return 'Obbligatorio'; return null; } Future applyRuntimeEffects({ required bool newEnabled, required bool oldEnabled, }) async { // Se non ho CollectionSource nel contesto, niente crash: applico solo storage + http. CollectionSource? source; try { source = context.read(); } catch (_) { source = null; } // OFF if (!newEnabled) { RemoteSyncBus.instance.setDisabled(); if (source != null) { final remotesInMemory = source.allEntries.where((e) => e.origin == RemoteOrigin.value).toSet(); if (remotesInMemory.isNotEmpty) { source.removeEntriesFromMemory(remotesInMemory); } } return; } // ON if (source == null) { // Non posso mostrare/nascondere, ma almeno imposto lo stato icona coerente await RemoteController.instance.initBusFromSettings(); return; } // Se sto passando OFF->ON, voglio fare: // - prima attivazione: FULL sync con overlay (contatore) // - successive: append DB + sync silenzioso final isFirstEnable = !(await RemoteController.instance.bootstrapDone()); if (isFirstEnable) { // FULL sync con overlay + set bootstrap_done on success await RemoteController.instance.fullSync( source: source, showOverlay: true, markBootstrapDoneOnSuccess: true, ); } else { // Mostra subito cache DB e sync in background silenzioso await source.appendRemoteEntriesFromDb(); // non blocchiamo la UI // ignore: unawaited_futures RemoteController.instance.fullSync( source: source, showOverlay: false, markBootstrapDoneOnSuccess: false, ); } } await showDialog( context: context, builder: (_) => StatefulBuilder( builder: (context, setStateDialog) => AlertDialog( title: const Text('Remote Settings'), content: Form( key: formKey, child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.min, children: [ SwitchListTile( title: const Text('Abilita remote'), value: enabled, onChanged: (v) => setStateDialog(() => enabled = v), contentPadding: EdgeInsets.zero, ), const SizedBox(height: 8), TextFormField( controller: baseUrlC, decoration: const InputDecoration(labelText: 'Base URL'), validator: validateBaseUrl, ), const SizedBox(height: 8), TextFormField( controller: indexC, decoration: const InputDecoration(labelText: 'Index path'), validator: validateIndex, ), const SizedBox(height: 8), TextFormField( controller: emailC, decoration: const InputDecoration(labelText: 'User/Email'), ), const SizedBox(height: 8), TextFormField( controller: pwC, obscureText: true, decoration: const InputDecoration(labelText: 'Password'), ), ], ), ), ), actions: [ TextButton( onPressed: () => Navigator.of(context).maybePop(), child: const Text('Annulla'), ), ElevatedButton.icon( onPressed: () async { if (!formKey.currentState!.validate()) return; final oldEnabled = s.enabled; final newEnabled = enabled; final upd = RemoteSettings( enabled: newEnabled, baseUrl: baseUrlC.text.trim(), indexPath: indexC.text.trim(), email: emailC.text.trim(), password: pwC.text, ); await upd.save(); // aggiorna subito base url/token await RemoteHttp.refreshFromSettings(); await RemoteHttp.warmUp(); // ✅ applica subito ON/OFF live (mostra/nascondi + sync) await applyRuntimeEffects(newEnabled: newEnabled, oldEnabled: oldEnabled); if (context.mounted) Navigator.of(context).pop(); }, icon: const Icon(Icons.save), label: const Text('Salva'), ), ], ), ), ); baseUrlC.dispose(); indexC.dispose(); emailC.dispose(); pwC.dispose(); } }