import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:ui'; import 'dart:io'; import '/data/models/message_model.dart'; import '/data/models/contact_model.dart'; import '/logic/contact_provider.dart'; import '/domain/services/api_service.dart'; import '/core/theme_manager.dart'; class ForwardContactPickerScreen extends StatefulWidget { final MessageModel message; const ForwardContactPickerScreen({super.key, required this.message}); @override State createState() => _ForwardContactPickerScreenState(); } class _ForwardContactPickerScreenState extends State { Contact? _selectedContact; bool _isInitLoading = true; SharedPreferences? _prefs; String? token; @override void initState() { super.initState(); _loadActiveChats(); } Future _loadActiveChats() async { try { final contactProvider = context.read(); await contactProvider.loadContacts(); final apiService = ApiService(); final accessToken = await apiService.getAccessToken(); final shared = await SharedPreferences.getInstance(); if (mounted) { setState(() { _prefs = shared; token = accessToken; }); } } catch (e) { debugPrint("Ошибка при загрузке данных для пересылки: $e"); } finally { if (mounted) { setState(() { _isInitLoading = false; }); } } } String _getDisplayName(Contact contact) { if (_prefs == null) return '${contact.name != 'Unknown' ? contact.name : ''} ${contact.surname != 'Unknown' ? contact.surname : ''}'.trim(); final id = contact.id; final savedName = _prefs!.getString('firstname_$id'); final savedSurname = _prefs!.getString('lastname_$id'); String? displayName; if (savedName != null && savedName.isNotEmpty) { displayName = savedName; } if (savedSurname != null && savedSurname.isNotEmpty) { (displayName == null || displayName.isEmpty) ? displayName = savedSurname : displayName += " $savedSurname"; } return displayName ?? '${contact.name != 'Unknown' ? contact.name : ''} ${contact.surname != 'Unknown' ? contact.surname : ''}'.trim(); } String _formatTime(DateTime? time) { if (time == null) return ''; final localTime = time.toLocal(); final hour = localTime.hour.toString().padLeft(2, '0'); final minute = localTime.minute.toString().padLeft(2, '0'); return '$hour:$minute'; } String _getInitials(String name) { if (name.isEmpty) return '?'; final names = name.trim().split(RegExp(r'\s+')).where((s) => s.isNotEmpty).toList(); if (names.length > 1) { return (names[0][0] + names[1][0]).toUpperCase(); } else if (names.isNotEmpty) { return names[0][0].toUpperCase(); } return '?'; } @override Widget build(BuildContext context) { final contactProvider = context.watch(); final contacts = contactProvider.contacts; final isLoading = _isInitLoading || contactProvider.isLoading; final themeProv = context.watch(); final colorScheme = Theme.of(context).colorScheme; return Scaffold( extendBodyBehindAppBar: true, appBar: AppBar( backgroundColor: colorScheme.surface.withOpacity(0.85), elevation: 0, scrolledUnderElevation: 0, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(bottom: Radius.circular(24)), ), flexibleSpace: ClipRRect( borderRadius: const BorderRadius.vertical(bottom: Radius.circular(24)), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10), child: Container(color: Colors.transparent), ), ), leading: IconButton( icon: Icon(Icons.arrow_back_rounded, color: Theme.of(context).colorScheme.onSurface), onPressed: () => Navigator.of(context).pop(), ), title: Text( 'Переслать...', style: TextStyle(fontWeight: FontWeight.bold, color: Theme.of(context).colorScheme.onSurface), ), iconTheme: IconThemeData(color: Theme.of(context).colorScheme.onSurface), actions: [ AnimatedOpacity( duration: const Duration(milliseconds: 200), opacity: _selectedContact != null ? 1.0 : 0.5, child: Padding( padding: const EdgeInsets.only(right: 8.0), child: ElevatedButton( onPressed: _selectedContact != null ? () => Navigator.of(context).pop(_selectedContact) : null, style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(horizontal: 20), backgroundColor: colorScheme.primary, foregroundColor: colorScheme.onPrimary, ), child: const Text('Далее'), ), ), ), ], ), body: Stack( children: [ SafeArea( child: () { if (isLoading) { return const Center(child: CircularProgressIndicator()); } if (contactProvider.error != null) { return Center( child: Padding( padding: const EdgeInsets.all(24.0), child: Text( 'Ошибка: ${contactProvider.error}', textAlign: TextAlign.center, style: TextStyle(color: colorScheme.outline), ), ), ); } if (contacts.isEmpty) { return Center( child: Text( 'Нет активных чатов для пересылки.', style: TextStyle(color: colorScheme.outline, fontSize: 15), ), ); } return ListView.builder( padding: const EdgeInsets.only(top: 8, left: 8, right: 8), itemCount: contacts.length, itemBuilder: (context, index) { final contact = contacts[index]; final isSelected = _selectedContact?.id == contact.id; final bool isDecrypted = contact.isLastMsgDecrypted; final String subtitleText = isDecrypted ? (contact.lastMessage == null ? "Нет сообщений" : "${contact.lastMessageType != null ? MessageModel.getMediaPreview(contact.lastMessageType!) : ''} ${contact.lastMessage}".trim()) : (contact.lastMessage != null ? "Ожидание дешифровки..." : "Нет сообщений"); final avatarUrl = contact.effectiveAvatarUrl; final bool hasAvatar = avatarUrl != null && avatarUrl.isNotEmpty; return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: ClipRRect( borderRadius: BorderRadius.circular(20), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), child: AnimatedContainer( duration: const Duration(milliseconds: 250), decoration: BoxDecoration( color: isSelected ? colorScheme.primary.withOpacity(0.2) : colorScheme.surfaceVariant.withOpacity(0.4), borderRadius: BorderRadius.circular(20), border: Border.all( color: isSelected ? colorScheme.primary : colorScheme.outlineVariant.withOpacity(0.2), width: isSelected ? 2 : 1, ), ), child: Material( color: Colors.transparent, child: InkWell( onTap: () { setState(() { _selectedContact = isSelected ? null : contact; }); }, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), child: Row( children: [ // Avatar CircleAvatar( radius: 26, backgroundColor: colorScheme.primaryContainer, child: hasAvatar ? ClipOval( child: Image.network( avatarUrl, fit: BoxFit.cover, width: 52, height: 52, loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { if (loadingProgress == null) return child; return Center( child: Text( _getInitials(_getDisplayName(contact)), style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onPrimaryContainer), ), ); }, errorBuilder: (context, error, stackTrace) { return Center( child: Text( _getInitials(_getDisplayName(contact)), style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onPrimaryContainer), ), ); }, ), ) : Center( child: Text( _getInitials(_getDisplayName(contact)), style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: colorScheme.onPrimaryContainer), ), ), ), const SizedBox(width: 12), // Name and Message Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( _getDisplayName(contact), maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), const SizedBox(height: 2), Text( subtitleText, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: colorScheme.outline), ), ], ), ), const SizedBox(width: 12), // Checkmark AnimatedSwitcher( duration: const Duration(milliseconds: 200), transitionBuilder: (child, animation) => ScaleTransition(scale: animation, child: child), child: isSelected ? Container( key: const ValueKey('checkmark'), width: 28, height: 28, decoration: BoxDecoration(color: colorScheme.primary, shape: BoxShape.circle), child: const Icon(Icons.check_rounded, color: Colors.white, size: 18), ) : Text( _formatTime(contact.lastMessageTime), key: ValueKey(_formatTime(contact.lastMessageTime)), textAlign: TextAlign.end, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(color: colorScheme.outline), ), ), ], ), ), ), ), ), ), ), ); }, ); }(), ), ], ), ); } }