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

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_callkit_incoming/flutter_callkit_incoming.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:just_audio/just_audio.dart';
import 'package:mohem_flutter_app/app_state/app_state.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/config/routes.dart';
import 'package:mohem_flutter_app/main.dart';
import 'package:mohem_flutter_app/models/chat/call.dart';
import 'package:mohem_flutter_app/models/chat/get_single_user_chat_list_model.dart';
import 'package:mohem_flutter_app/models/chat/webrtc_payloads.dart';
import 'package:mohem_flutter_app/provider/chat_provider_model.dart';
import 'package:mohem_flutter_app/ui/chat/call/chat_incoming_call_screen.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:signalr_netcore/hub_connection.dart';

class ChatCallProvider with ChangeNotifier, DiagnosticableTreeMixin {
  ///////////////////// Web RTC Video Calling //////////////////////
  // Video Call
  late RTCPeerConnection _pc;
  late ChatProviderModel chatProvModel;
  RTCVideoRenderer? localVideoRenderer;
  RTCVideoRenderer? remoteRenderer;

  final AudioPlayer player = AudioPlayer();
  MediaStream? _localStream;
  late CallDataModel outGoingCallData;
  bool isMicOff = false;
  bool isLoudSpeaker = false;
  bool isCamOff = false;
  bool isCallEnded = false;
  bool isVideoCall = false;
  bool isAudioCall = false;
  bool isCallStarted = false;
  bool isFrontCamera = true;
  late SingleUserChatModel incomingCallData;

  /// WebRTC Connection Variables
  bool isIncomingCallLoader = true;
  bool isIncomingCall = false;
  bool isOutGoingCall = false;
  bool isUserOnline = false;

  late BuildContext providerContext;

  List<MediaDeviceInfo> devices = [];
  var _videoDeviceId;

  void initCallListeners({required BuildContext context}) {
    providerContext = context;
    if (kDebugMode) {
      print("=================== Call Listeners Registered =======================");
    }
    chatHubConnection.on("OnCallAcceptedAsync", onCallAcceptedAsync);
    chatHubConnection.on("OnIceCandidateAsync", onIceCandidateAsync);
    chatHubConnection.on("OnOfferAsync", onOfferAsync);
    chatHubConnection.on("OnAnswerOffer", onAnswerOffer);
    chatHubConnection.on("OnHangUpAsync", onHangUpAsync);
    chatHubConnection.on("OnCallDeclinedAsync", onCallDeclinedAsync);
    // chatHubConnection.on("OnIncomingCallAsync", OnIncomingCallAsync);
  }

  // Audio Constraints
  Map<String, Object> audioConstraints = {
    "sampleRate": 8000,
    "sampleSize": 16,
    "channelCount": 2,
    "echoCancellation": true,
    "audio": true,
  };

  Future<void> init() async {
    _pc = await creatOfferWithCon();
    Future.delayed(const Duration(seconds: 2), () {
      connectIncomingCall();
    });
  }

  ///////////////////////////////////////////////OutGoing Call////////////////////////////////////////////////////

  Future<void> initLocalCamera({required ChatProviderModel chatProvmodel, required callData, required BuildContext context, bool isIncomingCall = false}) async {
    isCallEnded = false;
    chatProvModel = chatProvmodel;
    outGoingCallData = callData;
    await initStreams();
    await startCall(callType: isVideoCall ? "Video" : "Audio", context: context);
    _pc = await creatOfferWithCon();
    connectOutgoing();
    notifyListeners();
  }

  void connectOutgoing() {
    isOutGoingCall = true;
    notifyListeners();
  }

  Future<void> startCall({required String callType, required BuildContext context}) async {
    chatProvModel.isTextMsg = true;
    chatProvModel.isAttachmentMsg = false;
    chatProvModel.isVoiceMsg = false;
    chatProvModel.isReplyMsg = false;
    chatProvModel.isCall = true;
    chatProvModel.message.text = "Start $callType call ${outGoingCallData.receiverName.toString().replaceAll(".", " ")}";
    chatProvModel.sendChatMessage(
      context,
      targetUserId: outGoingCallData.receiverId!,
      userStatus: 1,
      userEmail: outGoingCallData.receiverEmail!,
      targetUserName: outGoingCallData.receiverName!,
    );
    await invoke(
      invokeMethod: "CallUserAsync",
      currentUserID: outGoingCallData.callerId!,
      targetUserID: outGoingCallData.receiverId!,
    );
    await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 4);
  }

  // OutGoing Listeners
  void onCallAcceptedAsync(List<Object?>? params) async {
    dynamic items = params!.toList();
    RTCSessionDescription description = await _createOffer();
    await _pc.setLocalDescription(description);
    dynamic payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()};
    invoke(invokeMethod: "OfferAsync", currentUserID: outGoingCallData.callerId!, targetUserID: items[0]["id"], data: jsonEncode(payload));
  }

  Future<void> onIceCandidateAsync(List<Object?>? params) async {
    dynamic items = params!.toList();
    if (isIncomingCall) {
      RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString()));
      if (_pc != null) {
        await _pc.addCandidate(RTCIceCandidate(data.candidate!.candidate, data.candidate!.sdpMid, data.candidate!.sdpMLineIndex));
      }
    } else {
      if (kDebugMode) {
        logger.i("res: " + items.toString());
      }
      RemoteIceCandidatePayLoad data = RemoteIceCandidatePayLoad.fromJson(jsonDecode(items.first.toString()));
      if (_pc != null) {
        await _pc.addCandidate(RTCIceCandidate(data.candidate!.candidate, data.candidate!.sdpMid, data.candidate!.sdpMLineIndex));
        if (!isCallStarted) {
          isCallStarted = true;
          notifyListeners();
          if (isCallStarted) {
            isIncomingCallLoader = false;
            isOutGoingCall = true;
            Navigator.push(
                providerContext,
                MaterialPageRoute(
                  builder: (BuildContext context) => StartCallPage(),
                )).then((value) {
              Navigator.of(providerContext).pop();
            });
          }
        }
      }
      notifyListeners();
    }
  }

  Future<void> onOfferAsync(List<Object?>? params) async {
    dynamic items = params!.toList();
    var data = jsonDecode(items.toString());
    if (isIncomingCall) {
      _pc.setRemoteDescription(RTCSessionDescription(data[0]["sdp"]["sdp"], data[0]["sdp"]["type"]));
      RTCSessionDescription description = await _createAnswer();
      await _pc.setLocalDescription(description);
      dynamic payload = {"target": data[0]["caller"], "caller": AppState().chatDetails!.response!.id, "sdp": description.toMap()};
      invoke(invokeMethod: "AnswerOfferAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, data: jsonEncode(payload));
    }
    // else {
    // RTCSessionDescription description = await _createAnswer();
    // await _pc.setLocalDescription(description);
    // var payload = {"target": items[0]["id"], "caller": outGoingCallData.callerId, "sdp": description.toMap()};
    // invoke(invokeMethod: "AnswerOffer", currentUserID: outGoingCallData.callerId!, targetUserID: items[0]["id"], data: jsonEncode(payload));
    // }
    notifyListeners();
  }

  //////////////////////////// OutGoing Call End ///////////////////////////////////////

  Future<bool> endCall({required bool isUserOnline}) async {
    if (isIncomingCall) {
      logger.i("-----------------------Endeddddd By Me---------------------------");
      if (chatHubConnection.state == HubConnectionState.Connected) {
        await invoke(invokeMethod: "HangUpAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 0);
        await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1);
      }
      isCallStarted = false;
      isVideoCall = false;
      isCamOff = false;
      isMicOff = false;
      isLoudSpeaker = false;
      isIncomingCall = false;
      isOutGoingCall = false;
      isAudioCall = false;

      if (isCallConnected) {
        if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
          print("------------------ PC Stopped ----------------------------");
          _pc.close();
          _pc.dispose();
        }
      }
      if (remoteRenderer != null) {
        remoteRenderer!.dispose();
        remoteRenderer = null;
      }
      if (localVideoRenderer != null) {
        localVideoRenderer!.dispose();
        localVideoRenderer = null;
      }

      if (_localStream != null) {
        _localStream!.dispose();
        _localStream = null;
      }
      if (chatHubConnection != null && !isUserOnline) {
        chatHubConnection.stop();
      }
      await FlutterCallkitIncoming.endAllCalls();
      return true;
    } else {
      if (isOutGoingCall) {
        await invoke(invokeMethod: "HangUpAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1);
        await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, userStatus: 1);
      } else if (isIncomingCall) {
        await invoke(invokeMethod: "UpdateUserStatusAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, userStatus: 1);
      }
      isCallStarted = false;
      isVideoCall = false;
      isCamOff = false;
      isMicOff = false;
      isLoudSpeaker = false;
      if (isCallConnected) {
        if (_pc.connectionState == RTCPeerConnectionState.RTCPeerConnectionStateConnected) {
          _pc.close();
          _pc.dispose();
        }
      }
      if (remoteRenderer != null) {
        remoteRenderer!.dispose();
        remoteRenderer = null;
      }
      if (localVideoRenderer != null) {
        localVideoRenderer!.dispose();
        localVideoRenderer = null;
      }

      if (_localStream != null) {
        _localStream!.dispose();
        _localStream = null;
      }
      isOutGoingCall = false;
      isIncomingCall = false;
      isAudioCall = false;
      return true;
    }
  }

  // Incoming Listeners

  void onAnswerOffer(List<Object?>? payload) async {
    // if (isIncomingCall) {
    //   // print("--------------------- On Answer Offer Async ---------------------------------------");
    //   //await invoke(invokeMethod: "InvokeMobile", currentUserID: AppState().getchatUserDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, debugData: {"On Answer Offer Async"});
    // } else {
    var items = payload!.toList();
    if (kDebugMode) {
      logger.i("res: " + items.toString());
    }
    CallSessionPayLoad data = CallSessionPayLoad.fromJson(jsonDecode(items.first.toString()));
    RTCSessionDescription description = RTCSessionDescription(data.sdp!.sdp, 'answer');
    _pc.setRemoteDescription(description);
    // }
  }

  void onHangUpAsync(List<Object?>? params) {
    print("--------------------- onHangUp ---------------------------------------");

    endCall(isUserOnline: isUserOnline).then((bool value) {
      if (isCallConnected) {
        Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
        isCallConnected = false;
      }
      isCallEnded = true;
    });
  }

  // Future<void> OnIncomingCallAsync(List<Object?>? params) async {
  //   print("--------------------- On Incoming Call ---------------------------------------");
  //   dynamic items = params!.toList();
  //   logger.d(items);
  //   // Map<String, dynamic> json = {
  //   //   "callerID": items[0]["id"],
  //   //   "callerName": items[0]["userName"],
  //   //   "callerEmail": items[0]["email"],
  //   //   "callerTitle": items[0]["title"],
  //   //   "callerPhone": null,
  //   //   "receiverID": AppState().chatDetails!.response!.id,
  //   //   "receiverName": AppState().chatDetails!.response!.userName,
  //   //   "receiverEmail": AppState().chatDetails!.response!.email,
  //   //   "receiverTitle": AppState().chatDetails!.response!.title,
  //   //   "receiverPhone": AppState().chatDetails!.response!.phone,
  //   //   "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "),
  //   //   "callType": items[1] ? "Video" : "Audio",
  //   // };
  //   // CallDataModel callData = CallDataModel.fromJson(json);
  //   // ChatVoipCall().showCallkitIncoming(uuid: const Uuid().v4(), isOnline: true, incomingCallData: callData);
  //   //
  //   // if (!isOnIncomingCallPage) {
  //   //   Map<String, dynamic> json = {
  //   //     "callerID": items[0]["id"],
  //   //     "callerName": items[0]["userName"],
  //   //     "callerEmail": items[0]["email"],
  //   //     "callerTitle": items[0]["title"],
  //   //     "callerPhone": null,
  //   //     "receiverID": AppState().chatDetails!.response!.id,
  //   //     "receiverName": AppState().chatDetails!.response!.userName,
  //   //     "receiverEmail": AppState().chatDetails!.response!.email,
  //   //     "receiverTitle": AppState().chatDetails!.response!.title,
  //   //     "receiverPhone": AppState().chatDetails!.response!.phone,
  //   //     "title": AppState().chatDetails!.response!.userName!.replaceAll(".", " "),
  //   //     "callType": items[1] ? "Video" : "Audio",
  //   //   };
  //   //   CallDataModel callData = CallDataModel.fromJson(json);
  //   //   await Navigator.push(
  //   //     providerContext,
  //   //     MaterialPageRoute(
  //   //       builder: (BuildContext context) => IncomingCall(
  //   //         isVideoCall: items[1] ? true : false,
  //   //         outGoingCallData: callData,
  //   //       ),
  //   //     ),
  //   //   );
  //   //   isOnIncomingCallPage = true;
  //   // }
  // }

  void onCallDeclinedAsync(List<Object?>? params) {
    print("================= On Declained ========================");
    logger.d(params);
    // endCall().then((bool value) {
    //   if (value) {
    //     isCallEnded = true;
    //     notifyListeners();
    //   }
    // });
    if (params != null) {
      endCall(isUserOnline: isUserOnline).then((bool value) {
        //  if (isCallConnected) {
        Navigator.of(AppRoutes.navigatorKey.currentContext!).pop();
        // isCallConnected = false;
        // }
        isCallEnded = true;
      });
    }
  }

  //// Invoke Methods

  Future<void> invoke({required String invokeMethod, required int currentUserID, required int targetUserID, var data, int userStatus = 1, var debugData}) async {
    List<Object> args = [];
    if (invokeMethod == "CallUserAsync") {
      args = [currentUserID, targetUserID, isVideoCall];
    } else if (invokeMethod == "answerCallAsync") {
      args = [currentUserID, targetUserID];
    } else if (invokeMethod == "IceCandidateAsync") {
      args = [targetUserID, data];
    } else if (invokeMethod == "OfferAsync") {
      args = [targetUserID, data];
    } else if (invokeMethod == "AnswerOfferAsync") {
      args = [targetUserID, data];
      // json In Data
    } else if (invokeMethod == "UpdateUserStatusAsync") {
      args = [currentUserID, userStatus];
    } else if (invokeMethod == "HangUpAsync") {
      args = [currentUserID, targetUserID];
    } else if (invokeMethod == "InvokeMobile") {
      args = [debugData];
    }
    try {
      await chatHubConnection.invoke("$invokeMethod", args: args);
    } catch (e) {
      logger.w(e);
    }
  }

  void stopListeners() async {
    chatHubConnection.off('OnCallDeclinedAsync');
    chatHubConnection.off('OnCallAcceptedAsync');
    chatHubConnection.off('OnIceCandidateAsync');
    chatHubConnection.off('OnAnswerOffer');
  }

  void playRingtone() async {
    player.stop();
    await player.setVolume(1.0);
    String audioAsset = "";
    if (Platform.isAndroid) {
      audioAsset = "assets/audio/ring_60Sec.mp3";
    } else {
      audioAsset = "assets/audio/ring_30Sec.caf";
    }
    try {
      await player.setAsset(audioAsset);
      await player.load();
      player.play();
    } catch (e) {
      print("Error: $e");
    }
  }

  //////////////////// Web RTC Offers & Connections ////////////////////////

  Future<RTCPeerConnection> creatOfferWithCon() async {
    Map<String, dynamic> configuration = {
      "sdpSemantics": "plan-b",
      'iceServers': [
        {
          'urls': 'stun:15.185.116.59:3478',
        },
        {
          'urls': 'turn:15.185.116.59:3479',
          'username': 'admin',
          'credential': 'admin',
        },
      ]
    };
    Map<String, dynamic> offerSdpConstraints = {
      'mandatory': {
        'OfferToReceiveAudio': true,
        'OfferToReceiveVideo': true,
      },
      'optional': []
    };

    RTCPeerConnection pc = await createPeerConnection(configuration, offerSdpConstraints);
    await pc!.addStream(_localStream!);
    pc?.onConnectionState = (RTCPeerConnectionState state) {};
    pc?.onAddStream = (MediaStream stream) {
      remoteRenderer!.srcObject = stream;
      notifyListeners();
    };
    pc!.onIceCandidate = (RTCIceCandidate e) async {
      if (isIncomingCall) {
        if (e.candidate != null) {
          var payload = {"target": incomingCallData.targetUserId, "candidate": e.toMap()};
          invoke(invokeMethod: "IceCandidateAsync", currentUserID: AppState().chatDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!, data: jsonEncode(payload));
          notifyListeners();
        }
      } else {
        if (e.candidate != null) {
          var payload = {"target": outGoingCallData.callerId, "candidate": e.toMap()};
          invoke(invokeMethod: "IceCandidateAsync", currentUserID: outGoingCallData.callerId!, targetUserID: outGoingCallData.receiverId!, data: jsonEncode(payload));
        }
      }
    };
    // pc!.onTrack = (RTCTrackEvent event) async {
    //
    //   String streamId = const Uuid().toString();
    //   MediaStream remoteStream = await createLocalMediaStream(streamId);
    //   event.streams[0].getTracks().forEach((MediaStreamTrack element) {
    //     logger.i("Stream Track: " + element.id.toString());
    //    // remoteRenderer.srcObject = element;
    //     remoteStream.addTrack(element);
    //   });
    // };
    pc!.onSignalingState = (RTCSignalingState state) {
      logger.i("signaling state: " + state.name);
      // invoke(
      //     invokeMethod: "InvokeMobile",
      //     currentUserID: AppState().getchatUserDetails!.response!.id!,
      //     targetUserID: incomingCallData.targetUserId!,
      //     debugData: {"location": "Signaling", "parms": state.name});
    };
    pc!.onIceGatheringState = (RTCIceGatheringState state) {
      logger.i("rtc ice gathering state: " + state.name);
    };
    pc!.onIceConnectionState = (RTCIceConnectionState state) {
      if (RTCIceConnectionState.RTCIceConnectionStateFailed == state ||
          RTCIceConnectionState.RTCIceConnectionStateDisconnected == state ||
          RTCIceConnectionState.RTCIceConnectionStateClosed == state) {
        logger.i("Ice Connection State:" + state.name);
        // endCall().then((value) {
        //   notifyListeners();
        // });
      }
    };
    //  pc!.onRenegotiationNeeded = _onRenegotiate;
    return pc;
  }

  // void _onRenegotiate() async {
  //   try {
  //     print('onRenegotiationNeeded start');
  //     //  makingOffer = true;
  //     await _pc.setLocalDescription(await _pc.createOffer(videoConstraints));
  //     print('onRenegotiationNeeded state after setLocalDescription: ' + _pc.signalingState.toString());
  //     // send offer via callManager
  //     var localDesc = await _pc.getLocalDescription();
  //     // callManager.sendCallMessage(MsgType.rtc_offer, RtcOfferAnswer(localDesc.sdp, localDesc.type));
  //     print('onRenegotiationNeeded; offer sent');
  //   } catch (e) {
  //     print("onRenegotiationNeeded error: " + e.toString());
  //   } finally {
  //     //   makingOffer = false;
  //     print('onRenegotiationNeeded done');
  //   }
  // }

  Future<RTCSessionDescription> _createOffer() async {
    RTCSessionDescription description = await _pc!.createOffer();
    // _offer = true;
    return description;
  }

  Future<RTCSessionDescription> _createAnswer() async {
    RTCSessionDescription description = await _pc!.createAnswer();
    //  _offer = false;
    return description;
  }

  //////////////////// Web RTC End Offers ////////////////////

  //////////////////// CallPage Buttons //////////////////////

  void micOff() {
    isMicOff = !isMicOff;
    _localStream!.getAudioTracks().forEach((track) {
      track.enabled = !track.enabled;
    });
    notifyListeners();
  }

  void camOff() {
    isCamOff = !isCamOff;
    _localStream!.getVideoTracks().forEach((track) {
      track.enabled = !track.enabled;
    });
    // if (isCamOff) {
    //   isVideoCall = false;
    // } else {
    //   isVideoCall = true;
    // }
    notifyListeners();
  }

  void loudOn() {
    isLoudSpeaker = !isLoudSpeaker;
    remoteRenderer!.srcObject?.getAudioTracks().forEach((track) {
      if (isLoudSpeaker) {
        track.enableSpeakerphone(true);
      } else {
        track.enableSpeakerphone(false);
      }
    });
    notifyListeners();
  }

  void switchCamera() {
    isFrontCamera = !isFrontCamera;
    Helper.switchCamera(_localStream!.getVideoTracks()[0]);
    notifyListeners();
  }

  ///////////////// Incoming Call ///////////////////////////////

  Future<void> initStreams() async {
    List<MediaDeviceInfo> devices = await navigator.mediaDevices.enumerateDevices();
    localVideoRenderer = RTCVideoRenderer();
    remoteRenderer = RTCVideoRenderer();
    await localVideoRenderer!.initialize();

    _localStream ??= await navigator.mediaDevices.getUserMedia(isVideoCall
        // ? Platform.isIOS
        //     ? // iOS media constraints for maximum quality camera
        //     {
        //         'audio': true,
        //         'video': {
        //           'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera
        //           'width': {
        //             'ideal': 1080, // Set the ideal width (maximum quality)
        //           },
        //           'height': {
        //             'ideal': 1920, // Set the ideal height (maximum quality)
        //           },
        //           'frameRate': {
        //             'ideal': 30, // Set the ideal frame rate (adjust as needed)
        //           },
        //         },
        //       }
        //     : // Android media constraints for maximum quality camera
        //     {
        //         'audio': true,
        //         'video': {
        //           'facingMode': 'user', // Use 'user' for front camera, 'environment' for back camera
        //           'width': {
        //             'ideal': 1920, // Set the ideal width (maximum quality)
        //           },
        //           'height': {
        //             'ideal': 1080, // Set the ideal height (maximum quality)
        //           },
        //           'frameRate': {
        //             'ideal': 30, // Set the ideal frame rate (adjust as needed)
        //           },
        //         },
        //       }

      ?  {
                    "video": {
                      "mandatory": {
                        "width": {"min": 1080},
                        "height": {"min": 1920}
                      },
                      "optional": [
                        {'sourceId': devices[1].deviceId},
                        {
                          "width": {"max": 1080}
                        },
                        {"frameRate": 30},
                        {"facingMode": "user"}
                      ]
                    },
                    "frameRate": 30,
                    "width": 1080, //420,//640,//1280,
                    "height": 1920, //240//480//720
                    "audio": true,
                  }

        : audioConstraints);
    localVideoRenderer!.srcObject = _localStream;
    await remoteRenderer!.initialize();
    notifyListeners();
  }

  Future<void> startIncomingCallViaKit({bool isVCall = true, required var inCallData}) async {
    Utils.saveStringFromPrefs("isIncomingCall", "false");
    if (isVCall) {
      isVideoCall = isVCall;
    } else {
      isAudioCall = true;
    }
    await initStreams();
    isIncomingCall = true;
    incomingCallData = SingleUserChatModel.fromJson(inCallData);
    loudOn();
    // notifyListeners();
  }

  void connectIncomingCall() {
    invoke(invokeMethod: "answerCallAsync", currentUserID: AppState().getchatUserDetails!.response!.id!, targetUserID: incomingCallData.targetUserId!);
    isIncomingCallLoader = false;
    isIncomingCall = true;
    // isVideoCall = true;

    notifyListeners();
  }
}
