import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:hmg_patient_app/config/config.dart';
import 'package:hmg_patient_app/config/shared_pref_kay.dart';
import 'package:hmg_patient_app/core/model/notifications/get_notifications_response_model.dart';
import 'package:hmg_patient_app/locator.dart';
import 'package:hmg_patient_app/models/LiveCare/IncomingCallData.dart';
import 'package:hmg_patient_app/pages/DrawerPages/notifications/notification_details_page.dart';
import 'package:hmg_patient_app/pages/conference/zoom/call_screen.dart';
import 'package:hmg_patient_app/pages/landing/landing_page.dart';
import 'package:hmg_patient_app/pages/livecare/incoming_call.dart';
import 'package:hmg_patient_app/pages/webRTC/OpenTok/OpenTok.dart';
import 'package:hmg_patient_app/uitl/LocalNotification.dart';
import 'package:hmg_patient_app/uitl/app-permissions.dart';
import 'package:hmg_patient_app/uitl/date_uitl.dart';
import 'package:hmg_patient_app/uitl/penguin_method_channel.dart';
import 'package:hmg_patient_app/uitl/utils.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:firebase_messaging/firebase_messaging.dart' as fir;
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

// import 'package:flutter_ios_voip_kit/call_state_type.dart';
// import 'package:flutter_ios_voip_kit/flutter_ios_voip_kit.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get_it/get_it.dart';
import 'package:huawei_hmsavailability/huawei_hmsavailability.dart';
import 'package:huawei_push/huawei_push.dart' as h_push;
import 'package:permission_handler/permission_handler.dart';

import 'app_shared_preferences.dart';
import 'navigation_service.dart';

// |--> Push Notification Background
@pragma('vm:entry-point')
Future<dynamic> backgroundMessageHandler(dynamic message) async {
  print("Firebase backgroundMessageHandler!!!");
  fir.RemoteMessage message_;
  if (message is h_push.RemoteMessage) {
    // if huawei remote message convert it to Firebase Remote Message
    message_ = toFirebaseRemoteMessage(message);
    h_push.Push.localNotification({h_push.HMSLocalNotificationAttr.TITLE: 'Background Message', h_push.HMSLocalNotificationAttr.MESSAGE: "By: BackgroundMessageHandler"});
  }

  if (message.data != null && (message.data['is_call'] == 'true' || message.data['is_call'] == true)) {
    // showCallkitIncoming(message);
    _incomingCall(message.data);
    return;
  } else {
    GetNotificationsResponseModel notification = new GetNotificationsResponseModel();

    notification.createdOn = DateUtil.convertDateToString(DateTime.now());
    notification.messageTypeData = message.data['picture'];
    notification.message = message.data['message'];
    await NavigationService.navigateToPage(NotificationsDetailsPage(
      notification: notification,
    ));
  }
}

// Push Notification Background <--|

RemoteMessage toFirebaseRemoteMessage(h_push.RemoteMessage message) {
  final payload_data = jsonDecode(message.data!);
  final fire_message = RemoteMessage(
      from: message.from,
      collapseKey: message.collapseKey,
      data: payload_data['data'],
      messageId: message.messageId,
      sentTime: DateTime.fromMillisecondsSinceEpoch(message.sentTime! * 1000),
      ttl: message.ttl,
      category: null,
      messageType: message.type,
      notification: RemoteNotification(
        title: message.notification!.title!,
        titleLocArgs: (message.notification!.titleLocalizationArgs! ?? []).map((e) => e.toString()).toList(),
        titleLocKey: message.notification!.titleLocalizationKey!,
        body: message.notification!.body!,
        bodyLocArgs: (message.notification!.bodyLocalizationArgs ?? []).map((e) => e.toString()).toList(),
        bodyLocKey: message.notification!.bodyLocalizationKey,
        android: AndroidNotification(
          channelId: message.notification!.channelId,
          clickAction: message.notification!.clickAction,
          color: message.notification!.color,
          count: null,
          imageUrl: message.notification!.imageUrl!.path,
          link: message.notification!.link!.path,
          smallIcon: message.notification!.icon,
          sound: message.notification!.sound,
          ticker: message.notification!.ticker,
          tag: message.notification!.tag,
        ),
      ));
  return fire_message;
}

// callPage(String sessionID, String token, String isWebrtc, String callerIdString) async {
callPage(String sessionID, String token) async {
  // if (isWebrtc == "true"){
  //   String caller = callerIdString.split("*")[3];
  //   String receiver = callerIdString.split("*")[4];
  //   String host = callerIdString.split("*")[5];
  //   return StartVideoCall(caller: caller, receiver: receiver, iAmCaller: false, host: host);
  // }else{
  await NavigationService.navigateToPage(OpenTokConnectCallPage(apiKey: OPENTOK_API_KEY, sessionId: sessionID, token: token));
  // }
}

// Future<void> showCallkitIncoming(Map message) async {
//   // if (message['type'] == 'ReservationCallStart') {
//     var params = CallKitParams(
//         id: DateTime.now().millisecondsSinceEpoch.toString(),
//         nameCaller: 'Dr Sulaiman Al Habib',
//         appName: 'Dr Sulaiman Al Habib',
//         avatar: 'https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG',
//         handle: 'LiveCare Call',
//         type: 1,
//         duration: 60000,
//         textAccept: 'Accept',
//         textDecline: 'Decline',
//         textMissedCall: 'Missed call',
//         textCallback: 'Call back',
//         extra: <String, dynamic>{
//           // 'reservationID': message['id'],
//           'userId': '1a2b3c4d'
//         },
//         headers: <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
//         android: AndroidParams(
//           isCustomNotification: true,
//           isShowLogo: false,
//           isShowCallback: false,
//           ringtonePath: 'system_ringtone_default',
//           backgroundColor: '#424242FF',
//           // 'backgroundUrl': 'https://i.pravatar.cc/500',
//           actionColor: '#4CAF50',
//           incomingCallNotificationChannelName: "Incoming Call",
//           missedCallNotificationChannelName: "Missed Call",
//         ),
//         ios: IOSParams(
//             iconName: 'CallKitLogo',
//             handleType: '',
//             supportsVideo: true,
//             maximumCallGroups: 2,
//             maximumCallsPerCallGroup: 1,
//             audioSessionMode: 'default',
//             audioSessionActive: true,
//             audioSessionPreferredSampleRate: 44100.0,
//             audioSessionPreferredIOBufferDuration: 0.005,
//             supportsDTMF: true,
//             supportsHolding: true,
//             supportsGrouping: false,
//             supportsUngrouping: false,
//             ringtonePath: 'system_ringtone_default'));
//     await FlutterCallkitIncoming.showCallkitIncoming(params);
//   // } else if (message['type'] == 'ReservationCallFinished') {
//   //   await FlutterCallkitIncoming.endAllCalls();
//   // }
// }

_incomingCall(Map<String, dynamic> data) async {
  LandingPage.incomingCallData = IncomingCallData.fromJson(data);
  if (LandingPage.isOpenCallPage == false) {
    LandingPage.isOpenCallPage = true;
    final bool permited = await AppPermission.askVideoCallPermission(currentContext!);
    if (permited)
      await NavigationService.navigateToPage(
        IncomingCall(incomingCallData: LandingPage.incomingCallData),
      );

    LandingPage.isOpenCallPage = false;
  }
  await Future.delayed(Duration(milliseconds: 500));
  await AppSharedPreferences().remove('call_data');
}

class PushNotificationHandler {
  late BuildContext context;
  static final PushNotificationHandler _instance = PushNotificationHandler._internal();

  late HmsApiAvailability hmsApiAvailability;

  // final voIPKit = FlutterIOSVoIPKit.instance;

  late Timer timeOutTimer;
  bool isTalking = false;

  var data = {
    "AppointmentNo": "2016059247",
    "ProjectID": "15",
    "NotificationType": "10",
    "background": "0",
    "doctorname": "Call from postman",
    "clinicname": "LIVECARE FAMILY MEDICINE AND GP",
    "speciality": "General Practioner",
    "appointmentdate": "2022-01-19",
    "appointmenttime": "12:10",
    "PatientName": "Testing",
    "session_id": "1_MX40NjIwOTk2Mn5-MTY1NDE2NDQxMjc2Mn5xc3NCZkNIejJOdzgzTkg2TmlXblhQdnl-fg",
    "token":
        "T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9MTliNTA3NDAxYmU0MjI5OGY5NTcxZTdhNzQyMTcyZjRjMjBhNjljZTpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWTFOREUyTkRReE1qYzJNbjV4YzNOQ1prTkllakpPZHpnelRrZzJUbWxYYmxoUWRubC1mZyZjcmVhdGVfdGltZT0xNjU0MTY0NDEzJm5vbmNlPTAuNjM3ODkzNDk4NDQ2NTIxOSZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjU0MjUwODEzJmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9",
    "DoctorImageURL": "https://image.shutterstock.com/image-vector/sample-stamp-square-grunge-sign-260nw-1474408826.jpg",
    "callerID": "9920",
    "PatientID": "1231755",
    "is_call": "true"
  };

  PushNotificationHandler._internal();

  factory PushNotificationHandler() => _instance;

  static PushNotificationHandler getInstance() => _instance;

  // void _timeOut({
  //   int seconds = 30,
  // }) async {
  //   timeOutTimer = Timer(Duration(seconds: seconds), () async {
  //     print('🎈 example: timeOut');
  //     final incomingCallerName = await voIPKit.getIncomingCallerName();
  //     voIPKit.unansweredIncomingCall(
  //       skipLocalNotification: false,
  //       missedCallTitle: '📞 Missed call',
  //       missedCallBody: 'There was a call from $incomingCallerName',
  //     );
  //   });
  // }

  init(BuildContext context) async {
    this.context = context;

    if (Platform.isIOS) {
      // voIPKit.getVoIPToken().then((value) {
      //   print("APNS VOIP KIT TOKEN: $value");
      //   AppSharedPreferences().setString(APNS_TOKEN, value!);
      // });
      //
      // voIPKit.onDidUpdatePushToken = (String token) {
      //   print('🎈 example: onDidUpdatePushToken: $token');
      // };
      //
      // voIPKit.onDidReceiveIncomingPush = (
      //   Map<String, dynamic> payload,
      // ) async {
      //   print('🎈 example: onDidReceiveIncomingPush $payload');
      //   _timeOut();
      // };
      //
      // voIPKit.onDidRejectIncomingCall = (
      //   String uuid,
      //   String callerId,
      // ) async {
      //   try {
      //     print('🎈 example: onDidRejectIncomingCall $uuid - $callerId');
      //     timeOutTimer.cancel();
      //   } catch (err) {}
      // };
      //
      // voIPKit.onDidAcceptIncomingCall = (
      //   String uuid,
      //   String callerId,
      // ) async {
      //   print('🎈 example: onDidAcceptIncomingCall $uuid - $callerId');
      //   await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
      //   await voIPKit.callConnected();
      //   await Future.delayed(Duration(seconds: 1));
      //
      //   Navigator.pushNamed(
      //     locator<NavigationService>().navigatorKey.currentContext!,
      //     "zoom_call_page",
      //     arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false),
      //   );
      //
      //   await voIPKit.endCall();
      //
      //   // Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN,
      //   //     arguments: VideoArgus(
      //   //         reservationId: int.parse(callerId), token: null, isVideo: true));
      //
      //   timeOutTimer.cancel();
      // };
    }

    if (Platform.isAndroid) {
      try {
        if (!(await Utils.isGoogleServicesAvailable())) {
          h_push.Push.enableLogger();
          final result = await h_push.Push.setAutoInitEnabled(true);

          h_push.Push.onNotificationOpenedApp.listen((message) {
            newMessage(toFirebaseRemoteMessage(message));
          }, onError: (e) => print(e.toString()));

          h_push.Push.onMessageReceivedStream.listen((message) {
            newMessage(toFirebaseRemoteMessage(message));
          }, onError: (e) => print(e.toString()));

          h_push.Push.getTokenStream.listen((token) {
            onToken(token);
          }, onError: (e) => print(e.toString()));
          h_push.Push.getToken('');

          h_push.Push.registerBackgroundMessageHandler(backgroundMessageHandler);
        } else {
          final fcmToken = await FirebaseMessaging.instance.getToken();
          if (fcmToken != null) onToken(fcmToken);
        }
      } catch (ex) {
        print("Notification Exception: " + ex.toString());
      }
    }

    if (Platform.isIOS) {
      await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true, // Required to display a heads up notification
        badge: true,
        sound: true,
      );
      final permission = await FirebaseMessaging.instance.requestPermission();
      if (permission.authorizationStatus == AuthorizationStatus.denied) return;
    } else {}

    try {
      FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) async {
        if (message != null) {
          if (Platform.isIOS)
            await Future.delayed(Duration(milliseconds: 3000)).then((value) {
              if (message != null) newMessage(message);
            });
          else if (message != null) newMessage(message);
        }
      });
    } catch (ex) {}

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      print("Firebase onMessage!!!");
      if (Platform.isIOS)
        await Future.delayed(Duration(milliseconds: 3000)).then((value) {
          newMessage(message);
        });
      else
        newMessage(message);
    });

    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
      print("Firebase onMessageOpenedApp!!!");
      if (Platform.isIOS)
        await Future.delayed(Duration(milliseconds: 3000)).then((value) {
          newMessage(message);
        });
      else
        newMessage(message);
    });

    FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);

    FirebaseMessaging.instance.getToken(vapidKey: 'BHRJG8sIzcysWxPw3B6xQjz_85nUuCfU6EAmpH18kyUTmB2cj35IdFwCyWSab80SA1v6oBSWVh-p6PcHPw_y00Y').then((String? token) {
      print("Push Notification getToken: " + token!);
      onToken(token!);
    }).catchError((err) {
      print(err);
    });

    FirebaseMessaging.instance.onTokenRefresh.listen((fcm_token) {
      print("Push Notification onTokenRefresh: " + fcm_token);
      onToken(fcm_token);
    });

    // FirebaseMessaging.instance.getToken(vapidKey: 'BHRJG8sIzcysWxPw3B6xQjz_85nUuCfU6EAmpH18kyUTmB2cj35IdFwCyWSab80SA1v6oBSWVh-p6PcHPw_y00Y').then((String? token) {
    //   print("Push Notification getToken: " + token!);
    //   onToken(token!);
    // });
    // FirebaseMessaging.instance.getToken(vapidKey: 'BHRJG8sIzcysWxPw3B6xQjz_85nUuCfU6EAmpH18kyUTmB2cj35IdFwCyWSab80SA1v6oBSWVh-p6PcHPw_y00Y').then((String? token) {
    //   print("Push Notification getToken: " + token!);
    //   onToken(token!);
    // });

    // if (Platform.isIOS) {
    //   FirebaseMessaging.instance.getAPNSToken().then((value) {
    //     print("Push APNS getToken: " + value!);
    //   });
    // }

    FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
  }

  newMessage(RemoteMessage remoteMessage) async {
    print("Remote Message: " + remoteMessage.data.toString());
    if (remoteMessage.data.isEmpty) {
      return;
    }
    debugPrint('the value of the remote message is ${remoteMessage.data}');
    if (remoteMessage.data['is_call'] == 'true' || remoteMessage.data['is_call'] == true) {
      _incomingCall(remoteMessage.data);
      // showCallkitIncoming(remoteMessage.data);
    }
    else if (remoteMessage.data['is_navigation'] == 'true' || remoteMessage.data['is_navigation'] == true) {
      NavigationClinicDetails data = NavigationClinicDetails();
      data.clinicId = remoteMessage.data['clinic_Id'];
      data.patientId = remoteMessage.data['patient_Id'];
      data.projectId = remoteMessage.data['project_Id'];
      initPenguinSDK(data);
    } else {
      GetNotificationsResponseModel notification = new GetNotificationsResponseModel();

      notification.createdOn = DateUtil.convertDateToString(DateTime.now());
      notification.messageTypeData = remoteMessage.data['picture'];
      notification.message = remoteMessage.data['message'];
      notification.notificationType = remoteMessage.data["NotificationType"].toString();
      if (remoteMessage.data["NotificationType"] == "2") {
        notification.videoURL = remoteMessage.data["VideoUrl"];
      }

      await NavigationService.navigateToPage(NotificationsDetailsPage(
        notification: notification,
      ));
    }
  }

  initPenguinSDK(NavigationClinicDetails data) async {
    final bool permited = await AppPermission.askPenguinPermissions();
    if (!permited) {
      Map<Permission, PermissionStatus> statuses = await [
        Permission.location,
        Permission.bluetooth,
        Permission.bluetoothConnect,
        Permission.bluetoothScan,
        Permission.activityRecognition,
      ].request().whenComplete(() {
        PenguinMethodChannel().launch("penguin", "en", "1231755", details: data);
      });
    }
  }

  onToken(String token) async {
    // print("Push Notification Token: " + token);
    await AppSharedPreferences().setString(PUSH_TOKEN, token);
    DEVICE_TOKEN = token;
  }

  onResume() async {
    var call_data = await AppSharedPreferences().getObject('call_data');
    if (call_data != null) {
      _incomingCall(call_data);
    }
  }

  Future<void> requestPermissions() async {
    try {
      if (Platform.isIOS) {
        await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()?.requestPermissions(alert: true, badge: true, sound: true);
      } else if (Platform.isAndroid) {
        Map<Permission, PermissionStatus> statuses = await [
          Permission.notification,
          // Permission.camera,
          // Permission.audio,
          // Permission.microphone,
        ].request();
        print("=-=-=-=-=-=-=-=-=-=-");
        print(statuses[Permission.location]);
      }
    } catch (_) {
      debugPrint(_.toString());
    }
  }
}
