// lib/features/notifications/notification_service.dart
// Gestiona FCM: suscripción a topic, handlers foreground/background.
//
// Regla de privacidad: los payloads de push NUNCA contienen lat/lng.
// El backend solo manda title/body desde notificaciones.json.

import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:go_router/go_router.dart';

import '../../core/router/app_router.dart';

// Canal Android de alta prioridad para alertas de proximidad
const _kChannelId = 'recolecta_alerts';
const _kChannelName = 'Alertas de recolección';
const _kChannelDesc = 'Notificaciones de llegada del camión recolector';

/// Notifier simple: la EtaScreen lo escucha para refrescar sin polling.
class _FcmMessageNotifier extends ChangeNotifier {
  RemoteMessage? lastMessage;
  void notify(RemoteMessage msg) {
    lastMessage = msg;
    notifyListeners();
  }
}

// Handler de background/terminated (top-level, fuera de clase)
@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  // Solo loguear; la EtaScreen se refrescará cuando la app vuelva a foreground.
  debugPrint('[FCM background] ${message.notification?.title}');
}

class NotificationService {
  NotificationService._();

  static final _messaging = FirebaseMessaging.instance;
  static final _localNotifications = FlutterLocalNotificationsPlugin();
  static final onFcmMessage = _FcmMessageNotifier();

  /// Inicializar una sola vez en main.dart
  static Future<void> initialize() async {
    // Registrar handler de background
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    // Solicitar permisos (iOS + Android 13+)
    final settings = await _messaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );
    debugPrint('[FCM] Permission: ${settings.authorizationStatus}');

    // Canal Android
    const androidChannel = AndroidNotificationChannel(
      _kChannelId,
      _kChannelName,
      description: _kChannelDesc,
      importance: Importance.high,
    );
    await _localNotifications
        .resolvePlatformSpecificImplementation<
          AndroidFlutterLocalNotificationsPlugin
        >()
        ?.createNotificationChannel(androidChannel);

    // Inicializar flutter_local_notifications
    const initSettings = InitializationSettings(
      android: AndroidInitializationSettings('@mipmap/ic_launcher'),
      iOS: DarwinInitializationSettings(),
    );
    await _localNotifications.initialize(
      initSettings,
      onDidReceiveNotificationResponse: (response) {
        // Tap del banner mostrado en foreground por flutter_local_notifications
        _openNotificationsScreen();
      },
    );

    // Foreground: mostrar notificación local + notificar EtaScreen
    FirebaseMessaging.onMessage.listen((message) {
      _showLocalNotification(message);
      onFcmMessage.notify(message);
    });

    // Tap en notificación cuando la app estaba en background
    FirebaseMessaging.onMessageOpenedApp.listen((message) {
      onFcmMessage.notify(message);
      _openNotificationsScreen();
    });

    // Verificar si la app abrió desde una notificación (terminated)
    final initial = await _messaging.getInitialMessage();
    if (initial != null) {
      onFcmMessage.notify(initial);
      // Esperar a que el router termine de montar el árbol antes de navegar.
      WidgetsBinding.instance.addPostFrameCallback((_) {
        _openNotificationsScreen();
      });
    }
  }

  /// Navega a `/notifications` usando el Navigator raíz. Tolerante a que
  /// la app aún no esté montada (no hace nada en ese caso).
  static void _openNotificationsScreen() {
    final ctx = rootNavigatorKey.currentContext;
    if (ctx == null) {
      debugPrint('[FCM] tap recibido pero el navigator aún no está listo');
      return;
    }
    try {
      GoRouter.of(ctx).push('/notifications');
    } catch (e) {
      debugPrint('[FCM] no se pudo navegar a /notifications: $e');
    }
  }

  /// Suscribir al topic de la ruta del ciudadano.
  /// Llamar justo después de que verified = true en el domicilio.
  static Future<void> subscribeToRoute(String routeId) async {
    final topic = 'topic_$routeId';
    await _messaging.subscribeToTopic(topic);
    debugPrint('[FCM] Suscrito a $topic');
  }

  /// Desuscribir (al cambiar de domicilio / colonia)
  static Future<void> unsubscribeFromRoute(String routeId) async {
    final topic = 'topic_$routeId';
    await _messaging.unsubscribeFromTopic(topic);
    debugPrint('[FCM] Desuscrito de $topic');
  }

  static Future<void> _showLocalNotification(RemoteMessage message) async {
    final notification = message.notification;
    if (notification == null) return;

    // El payload del backend es solo title+body; NUNCA contiene coordenadas.
    await _localNotifications.show(
      notification.hashCode,
      notification.title,
      notification.body,
      NotificationDetails(
        android: AndroidNotificationDetails(
          _kChannelId,
          _kChannelName,
          channelDescription: _kChannelDesc,
          importance: Importance.high,
          priority: Priority.high,
          // Sin ningún campo de mapa o ubicación
        ),
        iOS: const DarwinNotificationDetails(
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
        ),
      ),
    );
  }
}
