import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:rental_income_tracker/state/rent_controller.dart'; class SettingsScreen extends StatefulWidget { const SettingsScreen({super.key}); @override State createState() => _SettingsScreenState(); } class _SettingsScreenState extends State { final TextEditingController _rentController = TextEditingController(); Future _confirmImport() async { final result = await showDialog( context: context, builder: (context) { return AlertDialog( title: const Text('Import backup file?'), content: const Text( 'This will overwrite current local settings and logged entries with the contents of the selected backup file.', ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: const Text('Cancel'), ), FilledButton( onPressed: () => Navigator.of(context).pop(true), child: const Text('Import'), ), ], ); }, ); return result ?? false; } @override void didChangeDependencies() { super.didChangeDependencies(); final controller = context.read(); _rentController.text = controller.settings.rentUsd.toStringAsFixed(2); } @override void dispose() { _rentController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Consumer( builder: (context, controller, _) { return Scaffold( appBar: AppBar(title: const Text('Settings')), body: ListView( padding: const EdgeInsets.all(16), children: [ TextField( controller: _rentController, keyboardType: const TextInputType.numberWithOptions( decimal: true, ), decoration: const InputDecoration( labelText: 'Monthly rent (USD)', border: OutlineInputBorder(), ), ), const SizedBox(height: 12), FilledButton( onPressed: () async { final value = double.tryParse(_rentController.text.trim()); if (value == null || value <= 0) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Enter a valid rent amount.'), ), ); return; } await controller.updateRentUsd(value); if (!context.mounted) { return; } ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Rent updated.')), ); }, child: const Text('Save rent amount'), ), const SizedBox(height: 12), SwitchListTile( title: const Text('Unit occupied'), subtitle: const Text( 'When turned off, current and future months are marked Not occupied and reminders stop.', ), value: controller.settings.occupied, onChanged: (value) async { await controller.setOccupied(value); }, ), const Divider(height: 24), FilledButton.icon( onPressed: () async { await controller.backfillLastYear(); if (!context.mounted) { return; } if (controller.errorMessage == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Backfill finished for last year.'), ), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(controller.errorMessage!)), ); } }, icon: const Icon(Icons.history), label: const Text('Backfill last year (one click)'), ), const SizedBox(height: 12), FilledButton.icon( onPressed: () async { final directoryPath = await FilePicker.platform .getDirectoryPath(dialogTitle: 'Choose backup folder'); if (directoryPath == null || !context.mounted) { return; } final path = await controller.exportBackupToDirectory( directoryPath, ); if (!context.mounted) { return; } ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Backup saved to $path')), ); }, icon: const Icon(Icons.download), label: const Text('Create backup'), ), const SizedBox(height: 12), FilledButton.icon( onPressed: () async { final shouldImport = await _confirmImport(); if (!shouldImport || !context.mounted) { return; } final result = await FilePicker.platform.pickFiles( dialogTitle: 'Choose backup file', type: FileType.custom, allowedExtensions: ['json'], withData: false, ); final filePath = result?.files.single.path; if (filePath == null || !context.mounted) { return; } try { final path = await controller.importBackupFromFile( filePath, ); if (!context.mounted) { return; } _rentController.text = controller.settings.rentUsd .toStringAsFixed(2); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Imported backup from $path')), ); } catch (_) { if (!context.mounted) { return; } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( controller.errorMessage ?? 'Restore failed.', ), ), ); } }, icon: const Icon(Icons.restore), label: const Text('Import backup file'), ), const SizedBox(height: 16), const Text( 'ForexRateAPI key is loaded from FOREX_RATE_API_KEY via --dart-define-from-file=.env.', ), ], ), ); }, ); } }