import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:nearle/helpers/http_overrides.dart';

// Top-level background handler required by Firebase Messaging
@pragma('vm:entry-point')
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  HttpOverrides.global = MyHttpOverrides();
  try {
    await Firebase.initializeApp();
  } catch (_) {}

  await NotificationServce.display(message);
}

class NotificationServce {
  static final FirebaseMessaging _firebaseMessaging =
      FirebaseMessaging.instance;
  static final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();
  static final AudioPlayer _player = AudioPlayer();
  static String _channelId = 'Nearle';
  static bool _isPlaying = false;

  static const AndroidNotificationChannel channel = AndroidNotificationChannel(
    'Nearle',
    'Nearle Notification',
    description: 'Channel for Nearle notifications',
    importance: Importance.max,
    playSound: true,
    enableVibration: true,
    showBadge: true,
  );

  static Future<void> initialize(BuildContext context) async {
    try {
      final prefs = await SharedPreferences.getInstance();
      final alreadyInit = prefs.getBool('notifications_init_done') ?? false;
      if (alreadyInit) {
        return;
      }

    await FirebaseMessaging.instance.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );

      final existing = (prefs.getString('order_alert_sound') ?? '').trim();
      if (existing.isEmpty) {
        await prefs.setString('order_alert_sound', 'assets/audio/alert-1.mp3');
      }
      await prefs.setBool('notifications_init_done', true);
    } catch (_) {}

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

    await _applyChannelSoundFromPrefs();

    const InitializationSettings initializationSettings =
        InitializationSettings(
      android: AndroidInitializationSettings('@mipmap/ic_launcher'),
      iOS: DarwinInitializationSettings(
        requestSoundPermission: true,
        requestBadgePermission: true,
        requestAlertPermission: true,
        defaultPresentSound: true,
        defaultPresentBadge: true,
        defaultPresentBanner: true,
        defaultPresentAlert: true,
        defaultPresentList: true,
      ),
    );

    await _notificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveNotificationResponse: (NotificationResponse response) async {},
    );

    RemoteMessage? initialMessage =
        await _firebaseMessaging.getInitialMessage();
    if (initialMessage != null) {
      await _handleInitialMessage(initialMessage);
    }

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      await _handleMessage(message);
    });

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
      await _handleMessageOpenedApp(message);
    });
  }

  // ✅ Removed duplicated background handler (this was breaking your notifications)

  static Future<void> _handleInitialMessage(RemoteMessage message) async {
    if (message.notification != null) {
      await display(message);
    }
  }

  static Future<void> _handleMessage(RemoteMessage message) async {
    if (message.notification != null) {
      await display(message);
    }
  }

  static Future<void> _handleMessageOpenedApp(RemoteMessage message) async {}

  static Future<void> _applyChannelSoundFromPrefs() async {
    try {
      final prefs = await SharedPreferences.getInstance();
      String sel = (prefs.getString('order_alert_sound') ?? '').trim();
      if (sel.isEmpty) {
        sel = 'assets/audio/alert-1.mp3';
      }

      final fileName = sel.split('/').last;
      final base = fileName.split('.').first;
      final rawName = base.replaceAll(RegExp(r'[^a-zA-Z0-9_]'), '_');

      final androidImpl = _notificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>();

      if (androidImpl != null) {
        _channelId = 'Nearle_$rawName';

        final custom = AndroidNotificationChannel(
          _channelId,
          'Nearle Notification',
          description: 'Channel for Nearle notifications',
          importance: Importance.max,
          playSound: true,
          sound: RawResourceAndroidNotificationSound(rawName),
          enableVibration: true,
          showBadge: true,
        );

        await androidImpl.createNotificationChannel(custom);
      }
    } catch (_) {}
  }

  static Future<String?> _downloadAndSaveImage(
      String imageUrl, String fileName) async {
    try {
      final directory = await getTemporaryDirectory();
      final filePath = '${directory.path}/$fileName';
      final response = await http.get(Uri.parse(imageUrl));
      if (response.statusCode == 200) {
        final file = File(filePath);
        await file.writeAsBytes(response.bodyBytes);
        return filePath;
      }
      return null;
    } catch (_) {
      return null;
    }
  }

  static String? _extractImageUrl(RemoteMessage message) {
    String? imageUrl = message.data['image'] as String?;
    imageUrl ??= message.notification?.android?.imageUrl;
    imageUrl ??= message.notification?.apple?.imageUrl;
    return imageUrl;
  }

  static Future<void> _playSelectedSound({int times = 1}) async {
    try {
      if (_isPlaying) return;

      _isPlaying = true;

      final prefs = await SharedPreferences.getInstance();
      String selected = (prefs.getString('order_alert_sound') ?? '').trim();
      if (selected.isEmpty) {
        selected = 'assets/audio/alert-1.mp3';
      }

      final rel = selected.startsWith('assets/')
          ? selected.replaceFirst('assets/', '')
          : selected;

      await _player.stop();
      await _player.setReleaseMode(ReleaseMode.stop);

      for (int i = 0; i < times; i++) {
        await _player.play(AssetSource(rel));
        try {
          await _player.onPlayerComplete.first;
        } catch (_) {}
        if (i < times - 1) {
          await Future.delayed(const Duration(milliseconds: 120));
        }
      }
    } catch (_) {} finally {
      _isPlaying = false;
    }
  }

  /// Lightweight local notification helper for in-app events (no FCM message).
  static Future<void> showLocalNotification({
    required String title,
    required String body,
    bool playSound = true,
    String? payload,
  }) async {
    try {
      final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;

      final notificationDetails = NotificationDetails(
        android: AndroidNotificationDetails(
          _channelId,
          'Nearle Notification',
          importance: Importance.max,
          priority: Priority.high,
          icon: '@mipmap/ic_launcher',
          playSound: playSound,
          enableVibration: true,
          channelShowBadge: true,
          ongoing: false,
          autoCancel: true,
        ),
        iOS: DarwinNotificationDetails(
          presentAlert: true,
          presentBadge: true,
          presentSound: playSound,
          presentList: true,
          presentBanner: true,
        ),
      );

      await _notificationsPlugin.show(
        id,
        title,
        body,
        notificationDetails,
        payload: payload,
      );
    } catch (_) {}
  }

  static Future<void> display(RemoteMessage message) async {
    final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;
    final payload = jsonEncode({'id': id.toString(), 'data': message.data});

    final appState = WidgetsBinding.instance.lifecycleState;
    final bool isForeground = appState == AppLifecycleState.resumed;

    if (isForeground) {
      await _playSelectedSound(times: 5);
    }

    NotificationDetails notificationDetails;

    final imageUrl = _extractImageUrl(message);
    String? persistedImageUrl = imageUrl;
    String? persistedImagePath;

    if (imageUrl != null && imageUrl.isNotEmpty) {
      final imagePath = await _downloadAndSaveImage(
        imageUrl,
        'notification_image.jpg',
      );
      persistedImagePath = imagePath;

      notificationDetails = NotificationDetails(
        android: AndroidNotificationDetails(
          _channelId,
          'Nearle Notification',
          importance: Importance.max,
          priority: Priority.high,
          icon: '@mipmap/ic_launcher',
          playSound: !isForeground,
          enableVibration: true,
          fullScreenIntent: true,
          channelShowBadge: true,
          ongoing: false,
          autoCancel: true,
          styleInformation: imagePath != null
              ? BigPictureStyleInformation(FilePathAndroidBitmap(imagePath))
              : const DefaultStyleInformation(true, true),
        ),
        iOS: const DarwinNotificationDetails(
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
          presentList: true,
          presentBanner: true,
        ),
      );
    } else {
      notificationDetails = NotificationDetails(
        android: AndroidNotificationDetails(
          _channelId,
          'Nearle Notification',
          importance: Importance.max,
          priority: Priority.high,
          icon: '@mipmap/ic_launcher',
          playSound: !isForeground,
          enableVibration: true,
          fullScreenIntent: true,
          channelShowBadge: true,
          ongoing: false,
          autoCancel: true,
        ),
        iOS: const DarwinNotificationDetails(
          presentAlert: true,
          presentBadge: true,
          presentSound: true,
          presentList: true,
          presentBanner: true,
        ),
      );
    }

    if (isForeground) {
      final ctx = Get.context;
      if (ctx != null) {
        final title =
            message.notification?.title ?? message.data['title'] ?? 'Nearle';
        final body = message.notification?.body ?? message.data['body'] ?? '';

        ScaffoldMessenger.of(ctx).showSnackBar(
          SnackBar(
            content: Column(
              mainAxisSize: MainAxisSize.min,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(title, style: const TextStyle(fontWeight: FontWeight.w700)),
                if (body.isNotEmpty) Text(body),
              ],
            ),
            behavior: SnackBarBehavior.floating,
            margin: const EdgeInsets.all(16),
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(12),
            ),
            duration: const Duration(seconds: 3),
          ),
        );
      }
    } else {
      await _notificationsPlugin.show(
        id,
        message.notification?.title ?? message.data['title'] ?? 'Nearle',
        message.notification?.body ?? message.data['body'] ?? 'Notification',
        notificationDetails,
        payload: payload,
      );
    }

    try {
      final prefs = await SharedPreferences.getInstance();
      final nowIso = DateTime.now().toIso8601String();

      final title =
          message.notification?.title ?? message.data['title'] ?? 'Nearle';
      final body =
          message.notification?.body ?? message.data['body'] ?? '';

      final entry = {
        'id': id,
        'title': title,
        'body': body,
        'time': nowIso,
        'data': message.data,
        if (persistedImageUrl != null) 'imageUrl': persistedImageUrl,
        if (persistedImagePath != null) 'imagePath': persistedImagePath,
      };

      final existingRaw = prefs.getString('notifications_log');
      List<dynamic> list = [];

      if (existingRaw != null && existingRaw.isNotEmpty) {
        try {
          list = jsonDecode(existingRaw) as List<dynamic>;
        } catch (_) {}
      }

      list.insert(0, entry);

      if (list.length > 100) list = list.sublist(0, 100);

      await prefs.setString('notifications_log', jsonEncode(list));
    } catch (_) {}
  }
}
