/* eslint-disable @typescript-eslint/no-non-null-asserted-optional-chain */
import { useEffect, useRef, useState } from "react";
import Peer from "peerjs";
import { useStream } from "../context/StreamProvider";
import { useAppDispatch, useAppSelector } from "../utils/hooks";
import { socketInstance } from "../socket/socket";
import { useNavigate } from "react-router-dom";
import { updatePeerData } from "../store/Slices/PeerJsSlice";
import { CallEndedRes, UserJoinedRes } from "../types/ResType";
import {
  addConnectedUser,
  removeConnectedUser,
} from "../store/Slices/ConnectedUserSlice";

// const PEER_PORT = import.meta.env.VITE_PEER_PORT;
let peerInstance: Peer | null = null; // Global variable to prevent multiple instances

export const usePeer = () => {
  const { addUserStream, removeUserStream, updateUserStream, userStreams } =
    useStream();
  const { isVideoEnabled, isAudioEnabled, call_id, chat_id } = useAppSelector(
    (state) => state.PeerJsSlice,
  );
  const userData = useAppSelector((state) => state.userData);
  const [isAnyOneConnected, setIsAnyOneConnected] = useState(false);
  // let room_id = "3187049a-504f-4b11-9096-d11abb307813";
  const myPeer = useRef<Peer | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const socket = socketInstance(); // Store socket in a ref
  const ConnectedUser = useAppSelector((state) => state.ConnectedUser);
  const call_type = sessionStorage.getItem("call_type");
  const dispatch = useAppDispatch();

  useEffect(() => {
    if (ConnectedUser.length >= 2) {
      setIsAnyOneConnected(true);
    }
    if (ConnectedUser.length <= 1 && isAnyOneConnected) {
      // THIS DISPOSE WILL RUN WHEN ONLY ONE PARTICIPANT LEFT IN CALL BUT DUE TO NEW FLOW WE ONLY USE "call_ended" EVENT TO DISPOSE PEER
      // disposePeer();
    }
  }, [ConnectedUser]);

  useEffect(() => {
    if (!userData.user_id) {
      return;
    }
    if (peerInstance) {
      myPeer.current = peerInstance;
      return; // Use existing peer instead of creating a new one
    }

    // if (import.meta.env.VITE_IS_DEMO == "true") {
    peerInstance = new Peer("", {
      host: "peer.whoxachat.com",
      port: 443,
      path: "/",
      secure: true,
    });
    // } else {
    //   peerInstance = new Peer("", {
    //     host: import.meta.env.VITE_PEER_HOST, // 62.72.36.245
    //     port: PEER_PORT,
    //   });
    // }

    myPeer.current = peerInstance;

    peerInstance.on("open", (id) => {
      dispatch(
        updatePeerData({
          isVideoEnabled: call_type == "video" ? true : false,
        }),
      );
      navigator.mediaDevices
        .getUserMedia({
          video: call_type == "video" ? true : false,
          audio: true,
        })
        .then((stream) => {
          socket.emit("accept_call", {
            // room_id: room_id,
            call_id: call_id,
            peer_id: id,
            chat_id: chat_id,
            user_name: userData.user_name,
            user_id: userData.user_id,
          });

          streamRef.current = stream;

          addUserStream({
            peerId: myPeer.current?.id!,
            userName: "You",
            userId: userData.user_id,
            stream,
            isAudioEnabled,
            isVideoEnabled: call_type == "video" ? true : false,
            isLocal: true,
            currentVideo: true,
            isScreenSharing: false,
          });

          peerInstance?.on("call", (call) => {
            call.answer(stream);
            call.on("stream", (userStream) => {
              if (!sessionStorage.getItem("callStartTime")) {
                sessionStorage.setItem("callStartTime", Date.now().toString());
              }

              addUserStream({
                peerId: call.peer,
                stream: userStream,
                isLocal: false,
                userName: call.metadata.user_name || "Guest",
                userId: call.metadata.user_id,
                isAudioEnabled: true,
                isVideoEnabled: call_type == "video" ? true : false,
                currentVideo: false,
                isScreenSharing: false,
              });
            });
          });

          socket.on("user_joined", (userjoinData: UserJoinedRes) => {
            // Add user to connected user
            dispatch(
              addConnectedUser({
                profile_image: userjoinData.user.profile_pic,
                user_id: userjoinData.user.user_id,
                full_name: userjoinData.user.full_name,
                user_name: userjoinData.user.user_name,
              }),
            );
            if (userjoinData.user.user_id == userData.user_id) {
              return;
            }
            setTimeout(() => {
              const call = peerInstance?.call(userjoinData.peer_id, stream, {
                metadata: {
                  user_id: userData.user_id,
                  user_name: userData.full_name,
                  first_name: userData.first_name,
                },
              });

              call?.on("stream", (userStream) => {
                if (!sessionStorage.getItem("callStartTime")) {
                  sessionStorage.setItem(
                    "callStartTime",
                    Date.now().toString(),
                  );
                }
                addUserStream({
                  peerId: call.peer,
                  stream: userStream,
                  isLocal: false,
                  userName: userjoinData.user.full_name,
                  userId: userjoinData.user.user_id,
                  isAudioEnabled: true,
                  isVideoEnabled: call_type == "video" ? true : false,
                  currentVideo: false,
                  isScreenSharing: false,
                });
              });
            }, 100);
          });

          socket.on("user_left", (user_left_data: UserJoinedRes) => {
            removeUserStream(user_left_data?.peer_id);
            dispatch(removeConnectedUser(user_left_data?.user.user_id));
          });
          socket.on("call_ended", (user_left_data: CallEndedRes) => {
            disposePeer();
            // removeUserStream(user_left_data?.peer_id);
            // dispatch(removeConnectedUser(user_left_data?.users));
          });
          socket.on("call_changes", (data: any) => {
            updateUserStream(data?.peer_id!, {
              isAudioEnabled:
                data.isAudioEnabled != undefined ? data.isAudioEnabled : true,
              isVideoEnabled:
                data.isVideoEnabled != undefined ? data.isVideoEnabled : true,
            });
          });
        })
        .catch((err) => console.error("Media devices error:", err));
    });

    return () => { };
  }, [userData.user_id]);

  useEffect(() => {
    console.log(streamRef.current, "streamRef.current");
  }, [streamRef.current]);

  // Dispose peer and cleanup
  const disposePeer = () => {
    if (peerInstance) {
      peerInstance.destroy(); // Destroy peer instance
    }
    streamRef.current?.getTracks().forEach((track) => track.stop()); // Stop media tracks

    peerInstance = null; // Reset the global peer instance
    window.location.replace("/chat");
  };

  // Toggle video without re-fetching stream
  useEffect(() => {
    if (streamRef.current) {
      streamRef.current.getVideoTracks().forEach((track) => {
        track.enabled = isVideoEnabled;
      });
      updateUserStream(peerInstance?.id!, { isVideoEnabled });
    }
  }, [isVideoEnabled]);

  // Toggle audio without re-fetching stream
  useEffect(() => {
    const myId = myPeer.current?.id;
    if (!myId) return;

    const myStreamData = userStreams[myId];

    if (myStreamData?.stream) {
      myStreamData.stream.getAudioTracks().forEach((track) => {
        track.enabled = isAudioEnabled;
      });

      updateUserStream(myId, { isAudioEnabled });
    }
  }, [isAudioEnabled]);

  return { myPeer, streamRef };
};
