import 'dart:io';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:mc_common_app/classes/app_state.dart';
import 'package:mc_common_app/main.dart';
import 'package:permission_handler/permission_handler.dart';

abstract class FirebaseMessagingService {
  Future<String> getFirebaseToken();

  Future<void> initializeNotifications();
}

class FirebaseMessagingServiceImp implements FirebaseMessagingService {
  final FlutterLocalNotificationsPlugin flutterLocalNotifications;
  final FirebaseMessaging firebaseMessaging;

  FirebaseMessagingServiceImp({required this.firebaseMessaging, required this.flutterLocalNotifications});

  @override
  Future<String> getFirebaseToken() async => await firebaseMessaging.getToken() ?? "";

  Future<void> requestPermissions() async {
    if (Platform.isIOS) {
      await flutterLocalNotifications.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
    } else if (Platform.isAndroid) {
      AndroidFlutterLocalNotificationsPlugin? androidImplementation = flutterLocalNotifications.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>();
      bool? granted = await androidImplementation?.requestNotificationsPermission();
      if (granted == false) {
        await Permission.notification.request();
      }
    }
  }

  @override
  Future<void> initializeNotifications() async {
    await requestPermissions();
    AppState().setDeviceToken = await getFirebaseToken();
    AppState().setDeviceType = Platform.isAndroid ? "1" : "2";
    await Permission.notification.isDenied.then((bool value) {
      if (value) {
        Permission.notification.request();
      }
    });

    // initialise the plugin. app_icon needs to be a added as a drawable resource to the Android head project
    const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('ic_launcher');
    DarwinInitializationSettings initializationSettingsDarwin = const DarwinInitializationSettings(
      requestAlertPermission: true,
      requestBadgePermission: true,
      requestCriticalPermission: true,
      requestProvisionalPermission: true,
      requestSoundPermission: true,
      defaultPresentAlert: true,
      defaultPresentBadge: true,
      defaultPresentBanner: true,
      defaultPresentList: true,
      defaultPresentSound: true,
    );
    final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid, iOS: initializationSettingsDarwin);
    await flutterLocalNotifications.initialize(initializationSettings, onDidReceiveNotificationResponse: (notificationResponse) {}, );

    RemoteMessage? initialMessage = await FirebaseMessaging.instance.getInitialMessage();

    if (initialMessage != null) _handleNotification(initialMessage);

    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      if (message.notification != null) _handleNotification(message);
    });

    FirebaseMessaging.onMessageOpenedApp.listen(_handleNotification);

    FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);

    FirebaseMessaging.instance.onTokenRefresh.listen((String token) async {
      AppState().setDeviceToken = token;
    });
  }

  void _onDidReceiveLocalNotification(int id, String? title, String? body, String? payload) async {
    logger.i(body);
  }

  void _handleNotification(RemoteMessage message) async {
    logger.i(message.notification!.title);
    logger.i(message.notification!.body);

    displayNotification(title: message.notification!.title ?? '', body: message.notification!.body ?? '');
  }

  Future<void> displayNotification({required String title, required String body}) async {
    const AndroidNotificationDetails androidNotificationDetails = AndroidNotificationDetails(
      "0",
      'mowater',
      channelDescription: 'mowater_notifications',
      importance: Importance.max,
      priority: Priority.high,
      ticker: 'ticker',
    );

    const DarwinNotificationDetails iOSPlatformChannelSpecifics = DarwinNotificationDetails(threadIdentifier: 'thread_id');
    const NotificationDetails notificationDetails = NotificationDetails(android: androidNotificationDetails, iOS: iOSPlatformChannelSpecifics);
    await flutterLocalNotifications.show(0, title, body, notificationDetails, payload: 'item x');
  }
}

@pragma('vm:entry-point')
Future<dynamic> backgroundMessageHandler(RemoteMessage message) async {
  await Firebase.initializeApp();
}
