import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:relationship_saver/core/config/app_config.dart'; import 'package:relationship_saver/core/config/app_theme.dart'; import 'package:relationship_saver/features/auth/session_controller.dart'; import 'package:relationship_saver/features/local/local_repository.dart'; import 'package:relationship_saver/features/reminders/scheduling/reminder_scheduler_provider.dart'; import 'package:relationship_saver/features/share_intake/whatsapp_share_parser.dart'; import 'package:relationship_saver/features/shared/frosted_card.dart'; import 'package:relationship_saver/integrations/backend/models/backend_models.dart'; class SettingsView extends ConsumerWidget { const SettingsView({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final AuthSession? session = ref .watch(sessionControllerProvider) .asData ?.value; return LayoutBuilder( builder: (BuildContext context, BoxConstraints constraints) { final bool compact = constraints.maxWidth < 760; return Padding( padding: EdgeInsets.fromLTRB( compact ? 16 : 28, compact ? 16 : 24, compact ? 16 : 28, compact ? 20 : 28, ), child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Settings', style: Theme.of(context).textTheme.headlineMedium, ), const SizedBox(height: 6), Text( 'Environment and integration configuration for this build.', style: Theme.of(context).textTheme.bodyLarge?.copyWith( color: AppTheme.textSecondary, ), ), const SizedBox(height: 16), FrostedCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _SettingRow( compact: compact, label: 'Signed in as', value: session?.user.email ?? session?.user.id ?? 'Not signed in', ), const SizedBox(height: 12), _SettingRow( compact: compact, label: 'Gateway mode', value: AppConfig.useFakeBackend ? 'Fake (offline-safe)' : 'REST', ), const SizedBox(height: 12), _SettingRow( compact: compact, label: 'Base URL', value: AppConfig.backendBaseUrl, ), const SizedBox(height: 12), _SettingRow( compact: compact, label: 'Realtime', value: 'Planned later (SSE/WebSocket)', ), const SizedBox(height: 12), _SettingRow( compact: compact, label: 'Local notifications', value: AppConfig.enableLocalNotifications ? 'Enabled' : 'Disabled', ), const SizedBox(height: 14), Wrap( spacing: 8, runSpacing: 8, children: [ FilledButton.icon( onPressed: session == null ? null : () => _signOut(context, ref), icon: const Icon(Icons.logout_rounded), label: const Text('Sign Out'), ), OutlinedButton.icon( onPressed: session == null ? null : () { ref .read( sessionControllerProvider.notifier, ) .refreshProfile(); }, icon: const Icon(Icons.refresh_rounded), label: const Text('Refresh Profile'), ), OutlinedButton.icon( onPressed: AppConfig.enableLocalNotifications ? () => _requestNotificationPermissions( context, ref, ) : null, icon: const Icon( Icons.notifications_active_rounded, ), label: const Text('Request Notification Access'), ), OutlinedButton.icon( onPressed: () => _simulateWhatsAppShare(context, ref), icon: const Icon(Icons.message_rounded), label: const Text('Simulate WhatsApp Share'), ), ], ), ], ), ), const SizedBox(height: 16), FrostedCard( child: Text( 'Run options\n• Fake mode: flutter run --dart-define=USE_FAKE_BACKEND=true\n• REST mode: flutter run --dart-define=USE_FAKE_BACKEND=false --dart-define=BACKEND_BASE_URL=https://your-api', style: Theme.of(context).textTheme.bodyLarge, ), ), ], ), ), ); }, ); } Future _signOut(BuildContext context, WidgetRef ref) async { await ref.read(sessionControllerProvider.notifier).signOut(); if (context.mounted) { ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('Signed out.'))); } } Future _requestNotificationPermissions( BuildContext context, WidgetRef ref, ) async { final bool granted = await ref .read(reminderSchedulerProvider) .requestPermissions(); if (!context.mounted) { return; } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( granted ? 'Notification access granted.' : 'Notification access not granted.', ), ), ); } Future _simulateWhatsAppShare( BuildContext context, WidgetRef ref, ) async { final _ShareSimulationDraft? draft = await showDialog<_ShareSimulationDraft>( context: context, builder: (BuildContext context) => const _ShareSimulationDialog(), ); if (draft == null) { return; } final WhatsAppSharePayload parsed = WhatsAppShareParser.parse( draft.rawText, ); if (parsed.messageText.trim().isEmpty) { if (!context.mounted) { return; } ScaffoldMessenger.of( context, ).showSnackBar(const SnackBar(content: Text('Message text is empty.'))); return; } final SharedMessageIngestResult result = await ref .read(localRepositoryProvider.notifier) .ingestSharedMessage( SharedMessageIngestInput( sourceApp: 'whatsapp', messageText: parsed.messageText, sourceDisplayName: parsed.sourceDisplayName, sourceUserId: parsed.sourceUserId, sourceThreadId: parsed.sourceThreadId, sharedAt: DateTime.now(), ), ); if (!context.mounted) { return; } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( result.createdProfile ? 'Imported and created ${result.profileName}.' : 'Imported to ${result.profileName}.', ), ), ); } } class _SettingRow extends StatelessWidget { const _SettingRow({ required this.label, required this.value, required this.compact, }); final String label; final String value; final bool compact; @override Widget build(BuildContext context) { if (compact) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( label, style: Theme.of( context, ).textTheme.titleMedium?.copyWith(color: AppTheme.textSecondary), ), const SizedBox(height: 4), Text(value, style: Theme.of(context).textTheme.bodyLarge), ], ); } return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 140, child: Text( label, style: Theme.of( context, ).textTheme.titleMedium?.copyWith(color: AppTheme.textSecondary), ), ), Expanded( child: Text(value, style: Theme.of(context).textTheme.bodyLarge), ), ], ); } } class _ShareSimulationDraft { const _ShareSimulationDraft({required this.rawText}); final String rawText; } class _ShareSimulationDialog extends StatefulWidget { const _ShareSimulationDialog(); @override State<_ShareSimulationDialog> createState() => _ShareSimulationDialogState(); } class _ShareSimulationDialogState extends State<_ShareSimulationDialog> { late final TextEditingController _controller; @override void initState() { super.initState(); _controller = TextEditingController( text: '[2/18/26, 20:11] Ava Hart: Can we do coffee this Saturday?', ); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AlertDialog( title: const Text('Simulate WhatsApp Share'), content: TextField( controller: _controller, minLines: 3, maxLines: 6, decoration: const InputDecoration( hintText: 'Paste shared WhatsApp text payload', ), ), actions: [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel'), ), FilledButton( onPressed: () { final String rawText = _controller.text.trim(); if (rawText.isEmpty) { return; } Navigator.of(context).pop(_ShareSimulationDraft(rawText: rawText)); }, child: const Text('Import'), ), ], ); } }