import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:taxglide/consts/local_store.dart';
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
import 'package:taxglide/view/Main_controller/main_controller.dart';
import 'package:taxglide/view/screens/history/detail_screen.dart';
import 'package:taxglide/view/screens/notification_screen.dart';
import 'package:taxglide/router/consts_routers.dart';

// ─────────────────────────────────────────────────────────────────────────────
// Local Notifications setup (singleton plugin instance)
// ─────────────────────────────────────────────────────────────────────────────

final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
    FlutterLocalNotificationsPlugin();

/// Android notification channel used for all foreground chat/app notifications.
const AndroidNotificationChannel _channel = AndroidNotificationChannel(
  'taxglide_foreground', // id
  'TaxGlide Notifications', // name shown in system settings
  description: 'Foreground notifications for TaxGlide',
  importance: Importance.high,
  playSound: true,
  enableVibration: true,
);

/// Call once in main() after Firebase.initializeApp().
Future<void> initLocalNotifications() async {
  const initSettings = InitializationSettings(
    android: AndroidInitializationSettings('@mipmap/launcher_icon'),
    iOS: DarwinInitializationSettings(),
  );

  await flutterLocalNotificationsPlugin.initialize(
    initSettings,
    onDidReceiveNotificationResponse: (NotificationResponse response) {
      // Notification tapped while app is open – handled inside NotificationService.
      debugPrint('🔔 Local notification tapped: payload=${response.payload}');
      Get.find<NotificationService>().handleNavigationFromPayload(
        response.payload,
      );
    },
  );

  // Create the Android channel (no-op on iOS).
  await flutterLocalNotificationsPlugin
      .resolvePlatformSpecificImplementation<
        AndroidFlutterLocalNotificationsPlugin
      >()
      ?.createNotificationChannel(_channel);

  debugPrint('✅ LocalNotifications initialized');
}

// ─────────────────────────────────────────────────────────────────────────────
// NotificationService
// ─────────────────────────────────────────────────────────────────────────────

class NotificationService extends GetxController {
  final RemoteMessage? initialMessage;
  NotificationService(this.initialMessage);

  /// Running notification ID counter so multiple notifications can stack.
  int _notifId = 0;

  /// Shows a native Android system notification for a foreground message.
  /// Works from any context – WebSocket callbacks, FCM listeners, etc.
  ///
  /// [tag] is used as a deduplication key: if two sources (FCM + WebSocket)
  /// fire for the same chat/event, passing the same tag means Android will
  /// *replace* the first notification instead of showing a second one.
  void showForegroundNotification(RemoteMessage message, {String? tag}) {
    final String title =
        message.notification?.title ??
        message.data['title']?.toString() ??
        'New Notification';
    final String body =
        message.notification?.body ??
        message.data['body']?.toString() ??
        'You have a new update';

    // Build a simple payload string so tapping routes correctly.
    final String? type = message.data['type']?.toString();
    final String? id =
        message.data['page_id']?.toString() ?? message.data['id']?.toString();
    final String payload = (type != null && id != null) ? '$type:$id' : '';

    // Use the tag as dedup key; fall back to an incrementing ID so unrelated
    // notifications still stack correctly.
    final int notifId = tag != null ? tag.hashCode.abs() % 100000 : _notifId++;

    debugPrint(
      '🔔 NotificationService: showing local notification '
      '[id=$notifId tag=$tag title=$title]',
    );

    flutterLocalNotificationsPlugin.show(
      notifId,
      title,
      body,
      NotificationDetails(
        android: AndroidNotificationDetails(
          _channel.id,
          _channel.name,
          channelDescription: _channel.description,
          importance: Importance.high,
          priority: Priority.high,
          icon: '@mipmap/launcher_icon',
          playSound: true,
          enableVibration: true,
          styleInformation: BigTextStyleInformation(body),
          tag: tag, // same tag → replaces instead of duplicating
        ),
        iOS: const DarwinNotificationDetails(
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
        ),
      ),
      payload: payload,
    );
  }

  // ── Navigation helpers ──────────────────────────────────────────────────────

  /// Called when a local notification is tapped (payload = "type:id").
  void handleNavigationFromPayload(String? payload) {
    if (payload == null || payload.isEmpty) {
      _safeNavigate(() => Get.offAll(() => MainController()));
      return;
    }
    final parts = payload.split(':');
    final type = parts.isNotEmpty ? parts[0] : null;
    final idStr = parts.length > 1 ? parts[1] : null;
    handleNavigation({'type': type, 'id': idStr});
  }

  Future<void> handleNavigation(Map<String, dynamic> data) async {
    final LocalStore localStore = LocalStore();

    try {
      // ── Auth check ──────────────────────────────────────────────────────────
      final String? token = await localStore.getToken();
      if (token == null || token.isEmpty || token == 'null') {
        debugPrint('🔒 No valid token → Login');
        _safeNavigate(() => Get.offAllNamed(ConstRouters.login));
        return;
      }

      // Support both 'page'+'page_id' and 'type'+'id' payload formats.
      final String? type = data['page']?.toString() ?? data['type']?.toString();
      final String? idStr =
          data['page_id']?.toString() ??
          data['pageId']?.toString() ??
          data['id']?.toString();

      if (type == null || type.isEmpty) {
        debugPrint('⚠️ Invalid notification data: type is empty');
        _safeNavigate(() => Get.offAll(() => MainController()));
        return;
      }

      debugPrint('📍 Notification nav → type=$type  id=$idStr');

      if (type == 'chat') {
        final int chatId = int.tryParse(idStr ?? '') ?? 0;
        if (chatId == 0) {
          _safeNavigate(() => Get.offAll(() => MainController()));
          return;
        }
        debugPrint('💬 Navigating to Chat $chatId');
        _safeNavigate(() {
          try {
            if (Get.isDialogOpen ?? false) Get.back();
            if (Get.isBottomSheetOpen ?? false) Get.back();
            Navigator.of(Get.context!).popUntil((route) {
              return route.isFirst ||
                  route.settings.name == '/splash' ||
                  route.settings.name == '/MainController';
            });
          } catch (_) {}
          Future.delayed(const Duration(milliseconds: 200), () {
            if (Get.currentRoute == '/LiveChatScreen') {
              Get.off(
                () => LiveChatScreen(chatid: chatId, fileid: '0'),
                preventDuplicates: false,
              );
            } else {
              Get.to(
                () => LiveChatScreen(chatid: chatId, fileid: '0'),
                preventDuplicates: false,
              );
            }
          });
        });
      } else if (type == 'service') {
        final int serviceId = int.tryParse(idStr ?? '') ?? 0;
        if (serviceId == 0) {
          _safeNavigate(() => Get.offAll(() => MainController()));
          return;
        }
        debugPrint('📋 Navigating to Service $serviceId');
        _safeNavigate(
          () => Get.offAll(
            () => MainController(
              initialIndex: 2,
              child: DetailScreen(id: serviceId, sourceTabIndex: 2),
            ),
          ),
        );
      } else {
        debugPrint("❓ Unknown type '$type' → NotificationScreen");
        _safeNavigate(() {
          Get.offAll(() => const MainController());
          Future.delayed(
            const Duration(milliseconds: 300),
            () => Get.to(() => const NotificationScreen()),
          );
        });
      }
    } catch (e) {
      debugPrint('❌ Error handling notification nav: $e');
      try {
        final String? token = await localStore.getToken();
        if (token != null && token.isNotEmpty && token != 'null') {
          _safeNavigate(() => Get.offAll(() => MainController()));
        } else {
          _safeNavigate(() => Get.offAllNamed(ConstRouters.login));
        }
      } catch (_) {
        _safeNavigate(() => Get.offAllNamed(ConstRouters.login));
      }
    }
  }

  void _safeNavigate(Function action) {
    if (Get.key.currentState != null) {
      action();
      return;
    }
    int attempts = 0;
    Future.doWhile(() async {
      await Future.delayed(const Duration(milliseconds: 100));
      attempts++;
      if (Get.key.currentState != null) {
        action();
        return false;
      }
      return attempts < 20;
    });
  }
}
