import 'dart:io'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:path_provider/path_provider.dart'; import 'package:share_plus/share_plus.dart'; import 'package:cross_file/cross_file.dart'; import 'auth_screen.dart'; import '../../../core/network/dio_client.dart'; import '../providers/auth_provider.dart'; import '../../transactions/providers/providers.dart'; import '../../transactions/providers/paginated_transaction_provider.dart'; import '../../../core/theme/theme_provider.dart'; import '../../business/providers/business_mode_provider.dart'; import '../../business/providers/business_provider.dart'; import '../../projects/providers/project_mode_provider.dart'; import '../../projects/providers/project_provider.dart'; import '../../inventory/providers/products_provider.dart'; import '../../inventory/providers/product_categories_provider.dart'; import '../../inventory/providers/inventory_items_provider.dart'; import '../../inventory/providers/inventory_valuation_provider.dart'; import '../../inventory/providers/commodity_rates_provider.dart'; import '../../vendor/providers/vendors_provider.dart'; import '../../vendor/providers/purchase_orders_provider.dart'; import '../../sales/providers/customers_provider.dart'; import '../../sales/providers/invoices_provider.dart'; import '../../business/presentation/settings/business_settings_screen.dart'; import 'package:shared_preferences/shared_preferences.dart'; class ProfileScreen extends ConsumerStatefulWidget { const ProfileScreen({super.key}); @override ConsumerState createState() => _ProfileScreenState(); } class _ProfileScreenState extends ConsumerState with SingleTickerProviderStateMixin { bool _isExporting = false; String? _profileType; String _userName = 'Loading...'; String _userEmail = 'Loading...'; late AnimationController _animController; late Animation _fadeAnim; @override void initState() { super.initState(); _animController = AnimationController( vsync: this, duration: const Duration(milliseconds: 800), ); _fadeAnim = CurvedAnimation( parent: _animController, curve: Curves.easeOutCubic, ); _animController.forward(); _fetchProfileType(); } @override void dispose() { _animController.dispose(); super.dispose(); } Future _fetchProfileType() async { try { final res = await DioClient().dio.get('/account/setup/status'); if (mounted) { setState(() { _profileType = res.data['profileType']; _userName = res.data['name'] ?? 'Kifi User'; if (_userName.isEmpty) _userName = 'Kifi User'; _userEmail = res.data['email'] ?? ''; }); } } catch (e) { if (mounted) { setState(() { _userName = 'Kifi User'; _userEmail = ''; }); } } } String _getInitials(String name) { if (name.isEmpty || name == 'Kifi User' || name == 'Loading...') return 'KU'; final parts = name.trim().split(' '); if (parts.length > 1 && parts[1].isNotEmpty) { return '${parts[0][0]}${parts[1][0]}'.toUpperCase(); } return name.substring(0, name.length >= 2 ? 2 : 1).toUpperCase(); } Future _logout() async { await DioClient().clearToken(); try { final prefs = await SharedPreferences.getInstance(); await prefs.remove('is_business_mode'); } catch (_) {} try { ref.invalidate(categoryProvider); ref.invalidate(transactionProvider); ref.invalidate(paginatedTransactionProvider); ref.invalidate(budgetProvider); ref.invalidate(recurringTransactionProvider); ref.invalidate(walletProvider); ref.invalidate(invitationProvider); ref.invalidate(businessProfileProvider); ref.invalidate(businessFeatureProvider); ref.invalidate(businessModeProvider); ref.invalidate(productsProvider); ref.invalidate(productCategoriesProvider); ref.invalidate(inventoryItemsProvider); ref.invalidate(inventoryValuationProvider); ref.invalidate(commodityRatesProvider); ref.invalidate(vendorsProvider); ref.invalidate(purchaseOrdersProvider); ref.invalidate(customersProvider); ref.invalidate(invoicesProvider); ref.invalidate(projectsProvider); ref.invalidate(authControllerProvider); } catch (_) {} if (mounted) { Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (_) => const AuthScreen()), (route) => false, ); } } Future _exportData() async { setState(() => _isExporting = true); try { final bytes = await ref.read(apiRepositoryProvider).exportTransactions(); final tempDir = await getTemporaryDirectory(); final file = File('${tempDir.path}/transactions_export.csv'); await file.writeAsBytes(bytes); final xFile = XFile(file.path); await Share.shareXFiles([ xFile, ], text: 'Here is my Kifi transactions export.'); } catch (e) { if (mounted) ScaffoldMessenger.of( context, ).showSnackBar(SnackBar(content: Text('Export failed: $e'))); } finally { if (mounted) setState(() => _isExporting = false); } } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final primaryColor = Theme.of(context).primaryColor; final themeMode = ref.watch(themeProvider); return Scaffold( backgroundColor: Theme.of(context).scaffoldBackgroundColor, extendBodyBehindAppBar: true, appBar: AppBar( title: const Text( 'Profile', style: TextStyle(fontWeight: FontWeight.bold, letterSpacing: 1.2), ), backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, flexibleSpace: ClipRect( child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Container( color: Theme.of(context).scaffoldBackgroundColor.withOpacity(0.5), ), ), ), ), body: Stack( children: [ // Background Decorative Elements Positioned( top: -50, right: -50, child: Container( width: 200, height: 200, decoration: BoxDecoration( shape: BoxShape.circle, color: primaryColor.withOpacity(isDark ? 0.2 : 0.1), ), ), ), Positioned( bottom: -100, left: -50, child: Container( width: 300, height: 300, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.purple.withOpacity(isDark ? 0.15 : 0.08), ), ), ), // Main Content SafeArea( child: FadeTransition( opacity: _fadeAnim, child: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 600), child: ListView( physics: const BouncingScrollPhysics(), padding: const EdgeInsets.symmetric( horizontal: 24.0, vertical: 24.0, ), children: [ // Avatar Section Center( child: Hero( tag: 'profile_avatar', child: Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, gradient: LinearGradient( colors: [ primaryColor.withOpacity(0.8), primaryColor.withOpacity(0.5), ], begin: Alignment.topLeft, end: Alignment.bottomRight, ), boxShadow: [ BoxShadow( color: primaryColor.withOpacity(0.3), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: Center( child: Text( _getInitials(_userName), style: const TextStyle( fontSize: 40, fontWeight: FontWeight.bold, color: Colors.white, letterSpacing: 2, ), ), ), ), ), ), const SizedBox(height: 24), Text( _userName, style: Theme.of(context).textTheme.headlineSmall ?.copyWith(fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), if (_userEmail.isNotEmpty && _userEmail != 'Loading...') ...[ const SizedBox(height: 8), Text( _userEmail, style: TextStyle( color: isDark ? Colors.grey.shade400 : Colors.grey.shade600, fontSize: 16, ), textAlign: TextAlign.center, ), ], const SizedBox(height: 40), // Glassmorphism Card for Settings ClipRRect( borderRadius: BorderRadius.circular(24), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: Container( decoration: BoxDecoration( color: Theme.of( context, ).cardColor.withOpacity(isDark ? 0.3 : 0.6), borderRadius: BorderRadius.circular(24), border: Border.all( color: Colors.white.withOpacity( isDark ? 0.05 : 0.2, ), width: 1.5, ), ), child: Column( children: [ _buildSettingsTile( context: context, icon: LucideIcons.downloadCloud, iconColor: Colors.blue, title: 'Export Data to CSV', trailing: _isExporting ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, ), ) : const Icon( LucideIcons.chevronRight, size: 20, color: Colors.grey, ), onTap: _isExporting ? null : _exportData, ), _buildDivider(context, isDark), _buildSettingsTile( context: context, icon: LucideIcons.palette, iconColor: Colors.purple, title: 'Appearance', trailing: SegmentedButton( segments: const [ ButtonSegment( value: ThemeMode.light, icon: Icon(LucideIcons.sun, size: 16), ), ButtonSegment( value: ThemeMode.system, icon: Icon( LucideIcons.monitor, size: 16, ), ), ButtonSegment( value: ThemeMode.dark, icon: Icon(LucideIcons.moon, size: 16), ), ], selected: {themeMode}, onSelectionChanged: (Set newSelection) { ref .read(themeProvider.notifier) .setTheme(newSelection.first); }, showSelectedIcon: false, style: ButtonStyle( visualDensity: VisualDensity.compact, tapTargetSize: MaterialTapTargetSize.shrinkWrap, backgroundColor: WidgetStateProperty.resolveWith< Color? >((states) { if (states.contains( WidgetState.selected, )) { return primaryColor.withOpacity( 0.2, ); } return null; }), ), ), ), _buildDivider(context, isDark), Consumer( builder: (context, ref, child) { final isBusinessMode = ref.watch( businessModeProvider, ); return Column( children: [ if (_profileType == 'BUSINESS') ...[ _buildSwitchTile( context: context, icon: LucideIcons.briefcase, iconColor: Colors.orange, title: 'Business Mode', subtitle: 'Inventory and Sales Hub', value: isBusinessMode, onChanged: (val) => ref .read( businessModeProvider.notifier, ) .toggleMode(), ), if (isBusinessMode) ...[ _buildDivider(context, isDark), _buildSettingsTile( context: context, icon: LucideIcons.settings2, iconColor: Colors.grey.shade600, title: 'Business Settings', subtitle: 'Configure Taxes, Barcodes, etc.', trailing: const Icon( LucideIcons.chevronRight, size: 20, color: Colors.grey, ), onTap: () => Navigator.push( context, MaterialPageRoute( builder: (_) => const BusinessSettingsScreen(), ), ), ), ], _buildDivider(context, isDark), ], ], ); }, ), _buildDivider(context, isDark), _buildSettingsTile( context: context, icon: LucideIcons.helpCircle, iconColor: Colors.green, title: 'Help & Support', trailing: const Icon( LucideIcons.chevronRight, size: 20, color: Colors.grey, ), onTap: () {}, ), ], ), ), ), ), const SizedBox(height: 48), // Logout Button Container( width: double.infinity, decoration: BoxDecoration( borderRadius: BorderRadius.circular(16), gradient: LinearGradient( colors: [Colors.red.shade400, Colors.red.shade600], ), boxShadow: [ BoxShadow( color: Colors.red.withOpacity(0.3), blurRadius: 15, offset: const Offset(0, 5), ), ], ), child: ElevatedButton.icon( onPressed: () => _logout(), style: ElevatedButton.styleFrom( backgroundColor: Colors.transparent, foregroundColor: Colors.white, shadowColor: Colors.transparent, padding: const EdgeInsets.symmetric(vertical: 20), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), ), icon: const Icon(LucideIcons.logOut, size: 22), label: const Text( 'Log Out', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, letterSpacing: 1.0, ), ), ), ), const SizedBox(height: 40), ], ), ), ), ), ), ], ), ); } Widget _buildSettingsTile({ required BuildContext context, required IconData icon, required Color iconColor, required String title, String? subtitle, required Widget trailing, VoidCallback? onTap, }) { final isDark = Theme.of(context).brightness == Brightness.dark; return ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8), leading: Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: iconColor.withOpacity(isDark ? 0.2 : 0.1), borderRadius: BorderRadius.circular(12), ), child: Icon(icon, color: iconColor, size: 24), ), title: Text( title, style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 16), ), subtitle: subtitle != null ? Text( subtitle, style: TextStyle( fontSize: 13, color: isDark ? Colors.grey.shade400 : Colors.grey.shade600, ), ) : null, trailing: trailing, onTap: onTap, ); } Widget _buildSwitchTile({ required BuildContext context, required IconData icon, required Color iconColor, required String title, required String subtitle, required bool value, required ValueChanged onChanged, }) { return _buildSettingsTile( context: context, icon: icon, iconColor: iconColor, title: title, subtitle: subtitle, trailing: Switch( value: value, onChanged: onChanged, activeColor: iconColor, ), onTap: () => onChanged(!value), ); } Widget _buildDivider(BuildContext context, bool isDark) { return Divider( height: 1, indent: 76, endIndent: 20, color: Theme.of(context).dividerColor.withOpacity(isDark ? 0.1 : 0.05), ); } }