import 'dart:convert';
import 'package:chepuhagram/core/constants.dart';
import 'package:chepuhagram/domain/services/aPI_service.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../widgets/contact_tile.dart';
import '../screens/settings_screen.dart';
import '../screens/new_chat_screen.dart';
import '../screens/chat_screen.dart';
import '/logic/contact_provider.dart';
import '/logic/auth_provider.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:chepuhagram/domain/services/crypto_service.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:chepuhagram/main.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:package_info_plus/package_info_plus.dart';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'package:open_filex/open_filex.dart';
import '/data/datasources/ws_client.dart';

class ContactsScreen extends StatefulWidget {
  final int? targetChatId;

  const ContactsScreen({super.key, this.targetChatId});

  @override
  State<ContactsScreen> createState() => _ContactsScreenState();
}

class _ContactsScreenState extends State<ContactsScreen> with RouteAware {
  static const String _notificationLaunchKey = 'notification_launch_data';
  StreamSubscription<dynamic>? _socketSubscription;
  bool _isDownloading = false;
  double _downloadProgress = 0.0;
  CancelToken? _cancelToken = CancelToken();
  String? _latestApkUrl;
  bool _showUpdateBanner = false;

  @override
  void initState() {
    super.initState();
    print('ContactsScreen initState, targetChatId: ${widget.targetChatId}');
    _setupPushNotifications();
    final socketService = Provider.of<SocketService>(context, listen: false);
    _socketSubscription = socketService.messages.listen(_handleIncomingMessage);
    WidgetsBinding.instance.addPostFrameCallback((_) {
      final authProvider = context.read<AuthProvider>();
      final contactProvider = context.read<ContactProvider>();

      // Установить текущего пользователя и загрузить контакты с сообщениями
      print(
        'Setting current user ID in ContactProvider: ${authProvider.currentUserId}',
      );
      contactProvider.setCurrentUserId(authProvider.currentUserId);
      _initContacts();
    });
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _checkAppUpdate();
    });
  }

  Future<void> _initContacts() async {
    final contactProvider = context.read<ContactProvider>();
    // Ждем завершения загрузки контактов
    await contactProvider.loadContacts();

    print('Contacts loaded, checking targetChatId: ${widget.targetChatId}');

    // Дальнейшая логика выполнится только после того, как loadContacts завершится
    if (widget.targetChatId != null) {
      _navigateToTargetChat();
    } else {
      _checkSavedNotificationTarget();
    }
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context) as PageRoute);
  }

  @override
  void didPopNext() {
    print("Пользователь вернулся на этот экран!");
    _refreshData();
  }

  @override
  void dispose() {
    routeObserver.unsubscribe(this);
    _socketSubscription?.cancel();
    super.dispose();
  }

  void _refreshData() {
    print("Обновляем данные контактов и сообщений...");
    final contactProvider = context.read<ContactProvider>();

    contactProvider.loadContacts();
  }

  Future<void> _checkSavedNotificationTarget() async {
    final prefs = await SharedPreferences.getInstance();
    final savedData = prefs.getString(_notificationLaunchKey);
    if (savedData == null) {
      print('No saved notification data found in SharedPreferences');
      return;
    }

    try {
      final data = jsonDecode(savedData) as Map<String, dynamic>;
      print('Recovered saved notification data: $data');
      final senderId = int.tryParse(data['sender_id']?.toString() ?? '');
      final type = data['type']?.toString();

      // Поддерживаем старый payload (только sender_id) и новый (type+sender_id)
      if (senderId != null && (type == null || type == 'enc_message')) {
        print('Recovered targetChatId from saved data: $senderId');

        await prefs.remove(_notificationLaunchKey);
        _navigateToTargetChatWithId(senderId);
        return;
      }

      print('Saved notification data is not a valid payload: $data');
      await prefs.remove(_notificationLaunchKey);
    } catch (e) {
      print('Error parsing saved notification data: $e');
      await prefs.remove(_notificationLaunchKey);
    }
  }

  void _navigateToTargetChat() {
    if (widget.targetChatId == null) return;

    _navigateToTargetChatWithId(widget.targetChatId!);
  }

  void _navigateToTargetChatWithId(int targetChatId) async {
    print('_navigateToTargetChat called with targetChatId: $targetChatId');
    final contactProvider = context.read<ContactProvider>();
    try {
      final contact = contactProvider.contacts.firstWhere(
        (c) => c.id == targetChatId,
      );
      print('Auto-navigating to chat with contact: ${contact.username}');
      currentActiveChatContactId = targetChatId; // Устанавливаем активный чат
      final result = await Navigator.push(
        context,
        MaterialPageRoute(builder: (_) => ChatScreen(contact: contact)),
      );
      if (result != null) {
        _refreshData(); // Обновляем данные при возвращении с чата, если нужно
      }
    } catch (e) {
      print('Target contact with id $targetChatId not found: $e');
    }
  }

  Future<void> _checkAppUpdate() async {
    print('Проверка обновлений');
    PackageInfo packageInfo = await PackageInfo.fromPlatform();
    try {
      // 1. Запрос к вашему FastAPI
      final response = await http.get(
        Uri.parse('${AppConstants.baseUrl}/check-update'),
      );
      if (response.statusCode == 200) {
        final data = jsonDecode(response.body);
        final String latestVersion = data['latest_version'];
        print('444444');
        print(latestVersion);
        print(packageInfo.version);
        // Сравнение версий (предположим, у вас есть способ получить текущую версию)
        if (latestVersion != packageInfo.version) {
          setState(() {
            _showUpdateBanner = true;
            _latestApkUrl = data['apk_url'];
          });
        }
      }
    } catch (e) {
      print("Ошибка проверки обновлений: $e");
    }
  }

  Future<void> _setupPushNotifications() async {
    // Request permissions
    await FirebaseMessaging.instance.requestPermission();

    String? token = await FirebaseMessaging.instance.getToken();
    if (token != null) {
      ApiService apiService = ApiService();
      print(token);
      await apiService.updateFcmToken(token);
    }

    // Listen for token refresh
    FirebaseMessaging.instance.onTokenRefresh.listen((newToken) {
      ApiService apiService = ApiService();
      apiService.updateFcmToken(newToken);
      print('FCM Token refreshed: $newToken');
    });

    // Listen for foreground messages
    FirebaseMessaging.onMessage.listen(_handleIncomingMessage);

    // Handle notification tap when app was terminated/backgrounded
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('Notification tapped, app opened: ${message.data}');
      if (message.data['type'] == 'enc_message') {
        final senderId = int.tryParse(
          message.data['sender_id']?.toString() ?? '',
        );
        if (senderId != null) {
          _navigateToChatFromNotification(senderId);
        } else {
          print(
            'Notification tap contains invalid sender_id: ${message.data['sender_id']}',
          );
        }
      }
    });
  }

  void _navigateToChatFromNotification(int senderId) async {
    final contactProvider = context.read<ContactProvider>();
    print('Navigate to chat from notification with senderId: $senderId');

    // Если контакты еще не загружены, ждем их загрузки
    if (contactProvider.contacts.isEmpty) {
      print('Contacts not loaded yet, waiting...');
      // Ждем немного и пробуем снова
      Future.delayed(const Duration(milliseconds: 500), () {
        if (mounted) {
          _navigateToChatFromNotification(senderId);
        }
      });
      return;
    }

    try {
      final contact = contactProvider.contacts.firstWhere(
        (c) => c.id == senderId,
      );
      print('Navigating to chat from notification: ${contact.username}');
      currentActiveChatContactId = senderId; // Устанавливаем активный чат
      final result = await Navigator.push(
        context,
        MaterialPageRoute(builder: (_) => ChatScreen(contact: contact)),
      );
      if (result != null) {
        _refreshData(); // Обновляем данные при возвращении с чата, если нужно
      }
    } catch (e) {
      // Contact not found, stay on contacts screen
      print('Contact not found for notification: $senderId');
    }
  }

  Future<void> _handleIncomingMessage(dynamic data) async {
    if (data is RemoteMessage) {
      // FCM message
      await _handleFCMMessage(data);
    } else if (data is Map<String, dynamic>) {
      // WebSocket message
      print('WebSocket message received: $data');
      if (data['type'] == 'user_updated') {
        final userId = int.tryParse(data['user_id']?.toString() ?? '');
        if (userId != null) {
          final contactProvider = context.read<ContactProvider>();
          contactProvider.updateContact(userId);
        }
      }
    }
  }

  Future<void> _handleFCMMessage(RemoteMessage message) async {
    try {
      // Проверяем, не находимся ли мы уже в чате с отправителем
      final senderId = int.tryParse(
        message.data['sender_id']?.toString() ?? '',
      );
      if (senderId != null && currentActiveChatContactId == senderId) {
        print('Already in chat with sender $senderId, skipping notification');
        return;
      }

      // Ensure notification channel exists
      const AndroidNotificationChannel channel = AndroidNotificationChannel(
        'Messages',
        'Новые сообщения',
        description: 'Chat messages notifications',
        importance: Importance.high,
      );

      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
            AndroidFlutterLocalNotificationsPlugin
          >()
          ?.createNotificationChannel(channel);

      final crypto = CryptoService();
      final myPrivKey = await crypto.getPrivateKey();
      if (myPrivKey == null) {
        print('Private key not found, cannot decrypt message');
        return;
      }

      final sharedSecret = await crypto.deriveSharedSecret(
        myPrivKey,
        message.data['public_key'],
      );
      final decryptedText = await crypto.decryptMessage(
        message.data['content'],
        sharedSecret,
      );

      if (senderId == null) return;
      final String groupKey = 'ru.chepuhagram.app.$senderId';

      final prefs = await SharedPreferences.getInstance();
      final String? firstName = prefs.getString(
        'firstname_${message.data['sender_id']}',
      );
      final String? lastName = prefs.getString(
        'lastname_${message.data['sender_id']}',
      );
      final String localFullName = '${firstName ?? ''} ${lastName ?? ''}'
          .trim();

      final String title = localFullName.isNotEmpty
          ? localFullName
          : (message.data['username'] ?? 'Unknown');
      // Show local notification

      await flutterLocalNotificationsPlugin.show(
        senderId, 
        '',
        '',
        NotificationDetails(
          android: AndroidNotificationDetails(
            'Messages',
            'Новые сообщения',
            groupKey: groupKey, 
            setAsGroupSummary: true,
            importance: Importance.high,
            priority: Priority.high,
            groupAlertBehavior: GroupAlertBehavior.all,
          ),
        ),
      );
      await flutterLocalNotificationsPlugin.show(
        message.hashCode,
        title,
        decryptedText,
        NotificationDetails(
          android: AndroidNotificationDetails(
            'Messages',
            'Новые сообщения',
            groupKey: groupKey,
            importance: Importance.high,
            priority: Priority.high,
            showWhen: true,
          ),
        ),
        payload: jsonEncode({
          'type': 'enc_message',
          'sender_id': message.data['sender_id'],
          'timestamp':
              message.data['timestamp'] ?? DateTime.now().toIso8601String(),
        }),
      );

      if (message.data['type'] == 'enc_message') {
        final contactProvider = context.read<ContactProvider>();
        contactProvider.loadContacts();
      }
    } catch (e) {
      print('Error processing foreground FCM message: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    final double fabBottomPadding = _showUpdateBanner ? 120.0 : 16.0;
    return Scaffold(
      appBar: AppBar(
        title: Text(
          "Chepuhagram",
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
        centerTitle: false,
        elevation: 0,
        actions: [IconButton(icon: const Icon(Icons.search), onPressed: () {})],
      ),
      body: Stack(
        children: [
          Consumer<ContactProvider>(
            builder: (context, contactProvider, child) {
              if (contactProvider.isLoading) {
                return const Center(child: CircularProgressIndicator());
              }
              if (contactProvider.error != null) {
                return Center(child: Text('Error: ${contactProvider.error}'));
              }
              return ListView.separated(
                itemCount: contactProvider.contacts.length,
                separatorBuilder: (context, index) => Divider(
                  height: 1,
                  indent: 80,
                  color: Theme.of(context).colorScheme.primaryContainer,
                ),
                itemBuilder: (context, index) {
                  final contact = contactProvider.contacts[index];
                  return ContactTile(
                    contact: contact,
                    onTap: () async {
                      final result = await Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (_) => ChatScreen(contact: contact),
                        ),
                      );
                      if (result != null) {
                        _refreshData(); // Обновляем данные при возвращении с чата, если нужно
                      }
                    },
                  );
                },
              );
            },
          ),
          if (_showUpdateBanner)
            Positioned(
              left: 0,
              right: 0,
              bottom: 40,
              child: _buildUpdateBanner(),
            ),
        ],
      ),
      floatingActionButton: AnimatedPadding(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeInOut,
        padding: EdgeInsets.only(bottom: fabBottomPadding),
        child: FloatingActionButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (_) => const NewChatScreen()),
            );
          },
          child: const Icon(Icons.edit),
        ),
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            // Шапка меню с данными юзера
            Consumer<AuthProvider>(
              builder: (context, authProvider, _) {
                final username = authProvider.username;
                final displayName = authProvider.displayName;
                final initials =
                    (displayName.isNotEmpty ? displayName : (username ?? 'U'))
                        .trim()
                        .split(RegExp(r'\s+'))
                        .where((p) => p.isNotEmpty)
                        .take(2)
                        .map((p) => p[0].toUpperCase())
                        .join();

                return UserAccountsDrawerHeader(
                  accountName: Text(
                    displayName,
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.onSurface,
                    ),
                  ),
                  accountEmail: Text(
                    username == null || username.isEmpty ? '' : '@$username',
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.onSurface,
                    ),
                  ),
                  currentAccountPicture: CircleAvatar(
                    backgroundColor: authProvider.avatarUrl == null && authProvider.avatarPath == null
                        ? Theme.of(context).colorScheme.onSurface
                        : null,
                    backgroundImage: authProvider.avatarUrl != null
                        ? NetworkImage(authProvider.avatarUrl!)
                        : authProvider.avatarPath != null
                            ? FileImage(File(authProvider.avatarPath!))
                            : null,
                    child: (authProvider.avatarUrl == null && authProvider.avatarPath == null)
                        ? Text(
                            initials.isEmpty ? 'U' : initials,
                            style: TextStyle(
                              fontSize: 20,
                              fontWeight: FontWeight.bold,
                              color: Theme.of(context).colorScheme.primaryContainer,
                            ),
                          )
                        : null,
                  ),
                  decoration: BoxDecoration(
                    color: Theme.of(context).colorScheme.inversePrimary,
                  ),
                );
              },
            ),
            ListTile(
              leading: const Icon(Icons.settings),
              title: const Text("Настройки"),
              onTap: () {
                // Закрываем Drawer и переходим на экран настроек
                Navigator.pop(context);
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (_) => SettingsScreen()),
                );
              },
            ),
            ListTile(
              leading: const Icon(Icons.info_outline),
              title: const Text("О приложении"),
              onTap: () {
                /* ... */
              },
            ),
          ],
        ),
      ),
    );
  }

  Future<void> _startDownload() async {
    if (_latestApkUrl == null) return;

    // Показываем индикатор
    setState(() => _isDownloading = true);

    final dir = await getExternalStorageDirectory();
    final path = '${dir!.path}/update.apk';
    final file = File(path);

    // Удаляем старый файл, если он есть, чтобы гарантировать чистоту
    if (await file.exists()) {
      await file.delete();
    }

    try {
      // Скачиваем файл «в лоб»
      await Dio().download(
        _latestApkUrl!,
        path,
        cancelToken: _cancelToken,
        onReceiveProgress: (rec, total) {
          if (total != -1) {
            if (mounted) {
              setState(() => _downloadProgress = rec / total);
            }
          }
        },
      );

      // После успешного скачивания — установка
      final result = await OpenFilex.open(path);
      if (result.type != ResultType.done) {
        print("Ошибка при установке: ${result.message}");
      }
    } on DioException catch (e) {
      if (e.type != DioExceptionType.cancel) {
        print("Ошибка скачивания: $e");
      }
    } catch (e) {
      print("Ошибка: $e");
    } finally {
      if (mounted) {
        setState(() => _isDownloading = false);
      }
    }
  }

  Widget _buildUpdateBanner() {
    return Container(
      margin: const EdgeInsets.fromLTRB(
        12,
        0,
        12,
        16,
      ), // Отступы от краев и снизу
      child: Material(
        elevation: 6,
        borderRadius: BorderRadius.circular(12),
        child: Container(
          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.orange.shade600, Colors.deepOrange.shade400],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
            borderRadius: BorderRadius.circular(12),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Row(
                children: [
                  const Icon(
                    Icons.system_update_alt,
                    color: Colors.white,
                    size: 28,
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: Text(
                      _isDownloading
                          ? 'Скачивание ${(_downloadProgress * 100).toStringAsFixed(0)}%'
                          : "Доступно новое обновление!",
                      style: const TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                        fontSize: 16,
                      ),
                    ),
                  ),
                  TextButton(
                    onPressed: () async {
                      if (_isDownloading) {
                        // Если уже качаем — отменяем
                        _cancelToken?.cancel("Пользователь отменил загрузку");
                        setState(() {
                          _isDownloading = false;
                          _cancelToken = null; // Обязательно обнуляем токен!
                          _downloadProgress = 0.0;
                        });
                      } else {
                        // Если не качаем — запускаем
                        setState(() {
                          _isDownloading = true;
                          _cancelToken =
                              CancelToken(); // Создаем новый токен перед началом
                        });

                        // ВАЖНО: вызываем саму функцию скачивания
                        await _startDownload();
                      }
                    },
                    style: TextButton.styleFrom(
                      backgroundColor: Colors.white24,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                    child: Text(
                      _isDownloading ? "Отмена" : "Обновить",
                      style: const TextStyle(
                        color: Colors.white,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                  ),
                ],
              ),
              if (_isDownloading) ...[
                const SizedBox(height: 12),
                LinearProgressIndicator(
                  value: _downloadProgress,
                  color: Colors.white,
                  backgroundColor: Colors.white24,
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}
