import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart' as fir;
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_callkit_incoming/entities/android_params.dart';
import 'package:flutter_callkit_incoming/entities/call_kit_params.dart';
import 'package:flutter_callkit_incoming/entities/ios_params.dart';
import 'package:flutter_callkit_incoming/entities/notification_params.dart';
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
import 'package:flutter_ios_voip_kit_karmm/call_state_type.dart';
import 'package:flutter_ios_voip_kit_karmm/flutter_ios_voip_kit.dart';
import 'package:hmg_patient_app_new/core/api/api_client.dart';
import 'package:hmg_patient_app_new/core/api_consts.dart';
import 'package:hmg_patient_app_new/core/cache_consts.dart';
import 'package:hmg_patient_app_new/core/dependencies.dart';
import 'package:hmg_patient_app_new/core/utils/date_util.dart';
import 'package:hmg_patient_app_new/core/utils/utils.dart';
import 'package:hmg_patient_app_new/features/notifications/models/resp_models/notification_response_model.dart';
import 'package:hmg_patient_app_new/presentation/notifications/notification_details_page.dart';
import 'package:hmg_patient_app_new/services/navigation_service.dart';
import 'package:hmg_patient_app_new/widgets/routes/custom_page_route.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:uuid/uuid.dart';

// Global tracking variables for call state
bool _isCallInProgress = false;
String? _currentCallId;
Timer? _callTimeoutTimer;
String? _currentSessionId; // Store session ID for API call

// |--> Push Notification Background
@pragma('vm:entry-point')
Future<dynamic> backgroundMessageHandler(dynamic message) async {
  log("Firebase backgroundMessageHandler!!!");
  await Firebase.initializeApp();
  fir.RemoteMessage message_;

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

callPage(String sessionID, String token) async {}

_incomingCall(Map<String, dynamic> data) async {
  log('the value of the _incomingCall remote message is $data');

  // Check if there's already a call in progress to prevent duplicates
  // if (_isCallInProgress && _currentCallId != null) {
  //   log('⚠️ Call already in progress (ID: $_currentCallId), ignoring duplicate notification');
  //   return;
  // }

  String roomID = data['session_id'] ?? '';
  String callTypeID = data['AppointmentNo'] ?? '';

  log('🔍 Extracted from notification data:');
  log('   - roomID (session_id): "$roomID"');
  log('   - callTypeID (AppointmentNo): "$callTypeID"');

  // Generate unique call ID
  var _currentUuid = Uuid().v4();
  _currentCallId = _currentUuid;
  _isCallInProgress = true;
  _currentSessionId = roomID; // Store session ID for decline API call

  log('📞 Starting new call with ID: $_currentCallId, Session: $_currentSessionId');

  await Utils.saveStringFromPrefs(CacheConst.zoomRoomID, roomID);
  await Utils.saveStringFromPrefs(CacheConst.callTypeID, callTypeID);
  await Utils.saveBoolFromPrefs(CacheConst.isAppOpenedFromCall, true);

  log('💾 Saved to cache:');
  log('   - CacheConst.zoomRoomID: "$roomID"');
  log('   - CacheConst.callTypeID: "$callTypeID"');
  log('   - CacheConst.isAppOpenedFromCall: true');

  WidgetsFlutterBinding.ensureInitialized();

  int callKitType = callTypeID == '2' ? 0 : 1;

  CallKitParams callKitParams = CallKitParams(
    id: _currentUuid,
    nameCaller: "Dr Al Habib",
    appName: 'Dr Al Habib',
    avatar: 'https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG',
    type: callKitType,
    textAccept: 'Accept',
    textDecline: 'Decline',
    missedCallNotification: NotificationParams(
      showNotification: true,
      isShowCallback: false,
      subtitle: 'Missed call',
      callbackText: '',
    ),
    callingNotification: const NotificationParams(
      showNotification: false,
      isShowCallback: true,
      subtitle: 'Calling...',
      callbackText: 'Hang Up',
    ),
    duration: 30000,
    extra: <String, dynamic>{
      'userId': '1a2b3c4d',
      'callTypeID': callTypeID,
      'roomID': roomID,
    },
    headers: <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
    android: const AndroidParams(
        isImportant: true,
        isShowFullLockedScreen: true,
        isCustomNotification: true,
        isShowLogo: false,
        logoUrl: "https://play-lh.googleusercontent.com/FBNNpxb7m6eM6wtW7MV1Ffp6OXOGLI38q47zcvP29OCYA1yhYH5mZzl5itZi0TgOyZpG",
        ringtonePath: 'system_ringtone_default',
        backgroundColor: '#2E3039',
        backgroundUrl: 'https://saudipedia.com/en/saudipediaen/uploads/images/2024/08/02/97358.jpg',
        actionColor: '#4CAF50',
        textColor: '#FFFFFF',
        incomingCallNotificationChannelName: "Incoming Call",
        missedCallNotificationChannelName: "Missed Call",
        isShowCallID: false),
    ios: IOSParams(
      iconName: 'CallKitLogo',
      handleType: 'generic',
      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',
    ),
  );

  FlutterCallkitIncoming.unsilenceEvents();
  await FlutterCallkitIncoming.showCallkitIncoming(callKitParams);

  // Start 60-second timeout timer to auto-dismiss call
  _callTimeoutTimer?.cancel(); // Cancel any existing timer
  _callTimeoutTimer = Timer(Duration(seconds: 40), () async {
    log('⏱️ Call timeout (60 seconds) - auto dismissing call notification');
    await _endCallAndCleanup(_currentUuid);
  });

  await Future.delayed(Duration(milliseconds: 500));
}

// Helper method to end call and cleanup
Future<void> _endCallAndCleanup(String callId, {bool isDeclined = false}) async {
  try {
    // If call was declined, update session status via API
    if (isDeclined && _currentSessionId != null && _currentSessionId!.isNotEmpty) {
      await _updateSessionStatus(_currentSessionId!, 3, 'Patient');
    }

    // End the specific call
    await FlutterCallkitIncoming.endCall(callId);

    // Clear all calls to ensure clean state
    await FlutterCallkitIncoming.endAllCalls();

    // Reset tracking flags
    _isCallInProgress = false;
    _currentCallId = null;
    _currentSessionId = null;

    // Cancel timer
    _callTimeoutTimer?.cancel();
    _callTimeoutTimer = null;

    // Clear cache
    await Utils.saveBoolFromPrefs(CacheConst.isAppOpenedFromCall, false);
    await Utils.saveStringFromPrefs(CacheConst.zoomRoomID, '');
    await Utils.saveStringFromPrefs(CacheConst.callTypeID, '');
  } catch (e) {
    // Force reset flags even if there's an error
    _isCallInProgress = false;
    _currentCallId = null;
    _currentSessionId = null;
    _callTimeoutTimer?.cancel();
    _callTimeoutTimer = null;
  }
}

// Helper method to update session status via API
Future<void> _updateSessionStatus(String sessionId, int sessionStatus, String sessionEndedBy) async {
  try {
    final apiClient = getIt.get<ApiClient>();

    Map<String, dynamic> requestBody = {"Open_SessionID": sessionId, "SessionStatus": sessionStatus, "SessionEndedBy": sessionEndedBy};

    await apiClient.post(
      CHANGE_PATIENT_ER_SESSION,
      body: requestBody,
      onSuccess: (response, statusCode, {messageStatus, errorMessage}) {},
      onFailure: (error, statusCode, {messageStatus, failureType}) {
        log('❌ Failed to update session status: $error');
      },
    );
  } catch (e) {
    log('❌ Exception updating session status: $e');
  }
}

Future<void> openCallPage(BuildContext context) async {
  try {
    // if (incomingCallData!.background == "0") {
    // Zoom Call Page
    // Navigator.of(context).pop();
    Navigator.pushReplacementNamed(
      context,
      "zoom_call_page",
      // arguments: CallArguments(incomingCallData!.sessionId!, "123", "Patient", "40", "0", false, int.parse(incomingCallData!.appointmentNo!)),
    );
    // } else {
    //   // OpenTok Call Page
    //   await Navigator.of(context).pushReplacement(
    //     MaterialPageRoute(
    //       // fullscreenDialog: true,
    //       builder: (BuildContext context) {
    //         // final caller = widget.incomingCallData.callerID;
    //         // final receiver = widget.incomingCallData.receiverID;
    //         // final host = widget.incomingCallData.server;
    //         // if(widget.incomingCallData.isWebRTC == "true"){
    //         //   return StartVideoCall(caller: caller, receiver: receiver, iAmCaller: false, host: host);
    //         // }else{
    //         return OpenTokConnectCallPage(apiKey: OPENTOK_API_KEY, sessionId: incomingCallData!.sessionId!, token: incomingCallData!.token!);
    //       },
    //     ),
    //   );
    // }
  } catch (err) {
    log(err.toString());
    // await PlatformExceptionAlertDialog(
    //   exception: Exception(err),
    // ).show(context);
  }
}

// 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();
//   // }
// }

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 {
  //     log('🎈 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;

    await requestPermissions();

    if (Platform.isIOS) {
      voIPKit.getVoIPToken().then((value) {
        log("🎈 APNS VOIP KIT TOKEN: $value");
        Utils.saveStringFromPrefs(CacheConst.voipToken, value ?? "");
        // AppSharedPreferences().setString(APNS_TOKEN, value!);
      });

      voIPKit.onDidUpdatePushToken = (String token) {
        log('🎈 example: onDidUpdatePushToken: $token');
      };

      voIPKit.onDidReceiveIncomingPush = (
        Map<String, dynamic> payload,
      ) async {
        log('🎈 example: onDidReceiveIncomingPush $payload');
        // _timeOut();
      };

      voIPKit.onDidRejectIncomingCall = (
        String uuid,
        String callerId,
      ) async {
        try {
          log('🎈 example: onDidRejectIncomingCall $uuid - $callerId');
          timeOutTimer.cancel();
          // Cleanup on reject with API call
          if (_currentCallId != null) {
            await _endCallAndCleanup(_currentCallId!, isDeclined: true);
          }
        } catch (err) {
          log(err.toString());
        }
      };

      voIPKit.onDidAcceptIncomingCall = (
        String uuid,
        String callerId,
      ) async {
        log('🎈 example: onDidAcceptIncomingCall $uuid - $callerId');
        await voIPKit.acceptIncomingCall(callerState: CallStateType.calling);
        await voIPKit.callConnected();

        // Cleanup on accept - cancel timer and reset flags
        _callTimeoutTimer?.cancel();
        _callTimeoutTimer = null;
        _isCallInProgress = false;
        _currentCallId = null;
        await Future.delayed(Duration(seconds: 2)).then((val) async {
          await voIPKit.endCall();
        });

        // Navigator.pushNamed(
        //   locator<NavigationService>().navigatorKey.currentContext!,
        //   "zoom_call_page",
        //   arguments: CallArguments("hoover-dam", "123", "Patient", "40", "1", false),
        // );

        // Navigator.pushNamed(navigatorKey.currentContext!, VIDEO_CALL_SCREEN,
        //     arguments: VideoArgus(
        //         reservationId: int.parse(callerId), token: null, isVideo: true));

        // timeOutTimer.cancel();
      };
    }

    if (Platform.isAndroid) {
      try {
        final fcmToken = await FirebaseMessaging.instance.getToken().catchError((err) {
          log(err);
        });
        if (fcmToken != null) onToken(fcmToken);
        // }
      } catch (ex) {
        log("Notification Exception: $ex");
      }
      FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
    }

    if (Platform.isIOS) {
      final permission = await FirebaseMessaging.instance.requestPermission();
      await FirebaseMessaging.instance.getAPNSToken().then((value) async {
        log("APNS token: $value");
        await Utils.saveStringFromPrefs(CacheConst.apnsToken, value.toString());
      });
      await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true, // Required to display a heads up notification
        badge: true,
        sound: true,
      );
      // if (permission.authorizationStatus == AuthorizationStatus.denied) return;
    } else {
      final permission = await FirebaseMessaging.instance.requestPermission();
    }

    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 {
      log("Firebase onMessage!!!");
      // showCallkitIncoming();
      if (Platform.isIOS) {
        await Future.delayed(Duration(milliseconds: 3000)).then((value) {
          newMessage(message);
        });
      } else {
        newMessage(message);
      }
    });

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

    if (Platform.isIOS) {
      FirebaseMessaging.instance.getAPNSToken().then((String? token) {
        log("Push Notification getAPNSToken: ${token!}");
      }).catchError((err) {
        log("Push Notification getAPNSToken ERR: ${err.toString()}");
      });
    }

    FirebaseMessaging.instance.getToken().then((String? token) {
      log("Push Notification getToken: ${token!}");
      onToken(token!);
    }).catchError((err) {
      log(err.toString());
    });

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

    if (Platform.isAndroid) {
      final deviceInfo = DeviceInfoPlugin();
      final androidInfo = await deviceInfo.androidInfo;

      // int sdkInt = androidInfo.version.sdkInt ?? 0;
      // if (sdkInt >= 33) {
      //   await FlutterCallkitIncoming.requestFullIntentPermission();
      // }
    }
  }

  newMessage(RemoteMessage remoteMessage) async {
    log("Remote Message: ${remoteMessage.data}");
    if (remoteMessage.data.isEmpty) {
      return;
    }
    log('the value of the remote message is ${remoteMessage.data}');
    if (remoteMessage.data['is_call'] == 'true' || remoteMessage.data['is_call'] == true) {
      _incomingCall(remoteMessage.data);
      // showCallkitIncoming();
    } else {
      NotificationResponseModel notification = NotificationResponseModel();

      notification.createdOn = DateUtil.convertDateToString(DateTime.now());
      notification.isSentOn = DateUtil.convertDateToString(DateTime.now());
      notification.messageTypeData = remoteMessage.data['picture'];
      notification.messageType = notification.messageTypeData != null && notification.messageTypeData!.isNotEmpty ? "image" : "";
      notification.message = remoteMessage.data['message'];
      notification.notificationType = remoteMessage.data["NotificationType"].toString();
      if (remoteMessage.data["NotificationType"] == "2") {
        notification.videoURL = remoteMessage.data["VideoUrl"];
      }

      Navigator.of(getIt.get<NavigationService>().navigatorKey.currentContext!).push(
        CustomPageRoute(
          page: NotificationDetailsPage(
            notification: notification,
          ),
        ),
      );

      // 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,
      // ));
    }
  }

  onToken(String token) async {
    log("Push Notification Token: $token");
    await Utils.saveStringFromPrefs(CacheConst.pushToken, 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 FirebaseMessaging.instance.requestPermission(alert: true, badge: true, sound: true);
      } else if (Platform.isAndroid) {
        Map<Permission, PermissionStatus> statuses = await [
          Permission.notification,
          // Permission.camera,
          // Permission.audio,
          // Permission.microphone,
        ].request();
        log("=-=-=-=-=-=-=-=-=-=-");
        log(statuses[Permission.notification].toString());
      }
    } catch (_) {
      log(_.toString());
    }
  }
}
