/* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useRef, useState } from "react";
import { PixelStreamingWrapper2 } from "../components/PixelStreamingWrapper2";
import api from "../utils/api";
import { useParams, useSearchParams } from "react-router-dom";
import useStateRef from "react-usestateref";
import Peer from "peerjs";
import useIsAudioActive from "use-is-audio-active";
import { v4 as uuidv4 } from "uuid";
import { io } from "socket.io-client";
import IRemoteStream from "../types/IRemoteStream";
import Video from "../components/Video";
import ModalContainer2 from "../components/ModalContainer2";
import IUser from "../types/IUser";
import useModalStore from "../stores/useModalStore";
import SetNameModal from "../components/modals/stream/SetNameModal";
import useStreamStore from "../stores/useStreamStore";
import Button from "../components/ui/Button";
import HandOnIcon from "../components/icons/HandOnIcon";
import HandOffIcon from "../components/icons/HandOffIcon";
import MicroOnIcon from "../components/icons/MicroOnIcon";
import MicroOffIcon from "../components/icons/MicroOffIcon";
import CameraOnIcon from "../components/icons/CameraOnIcon";
import CameraOffIcon from "../components/icons/CameraOffIcon";
import { Trans } from "react-i18next";
import { isIOS, isMobile, useMobileOrientation } from "react-device-detect";
import WindowIcon from "../components/icons/WindowIcon";
import FullscreenIcon from "../components/icons/FullscreenIcon";
import ShareIcon from "../components/icons/ShareIcon";
import { useFullscreen } from "ahooks";
import InviteModal from "../components/modals/stream/InviteModal";
import Tooltip from "../components/Tooltip";
import { toast, ToastContainer } from "react-toastify";
import LoadingModal from "../components/modals/stream/LoadingModal";
import useSocketStore from "../stores/useSocketStore";
import useStreamUserStore from "../stores/useStreamUserStore";
import Chat2 from "../components/Chat2";
import Rotate64Icon from "../components/icons/Rotate64Icon";
import Draggable from "react-draggable";
import DesktopIcon from "../components/icons/DesktopIcon";
import MobileIcon from "../components/icons/MobileIcon";
import ChatIcon from "../components/icons/ChatIcon";
import useChatStore from "../stores/useChatStore";
// import ChatIcon from "../components/icons/ChatIcon";

// import MoreIcon from "../components/icons/MoreIcon";

const userId = uuidv4();

function StreamPage3() {
  const params = useParams();
  const [searchParams] = useSearchParams();
  const [WSUrl, setWSUrl] = useState<string>("");

  const localVideoRef = useRef<HTMLVideoElement>(null);
  const [localStream, setLocalStream] = useState<MediaStream>(
    new MediaStream()
  );
  const [remoteStreams, setRemoteStreams, remoteStreamsRef] = useStateRef<
    IRemoteStream[]
  >([]);
  const [peerId, setPeerId] = useState<string>("");
  const [peerInstance, setPeerInstance] = useState<Peer>();
  const [permission, setPermission] = useState<boolean>();
  const isSpeaking = useIsAudioActive({
    source: localStream.getTracks().length ? localStream : null,
  });
  const { me, users, setMe, setUsers } = useStreamUserStore();
  const isCallInit = useRef<boolean>(false);
  const [roomId] = useState<string>(params.id!);
  const { socket, setSocket } = useSocketStore();
  const { setModal } = useModalStore();
  const { name } = useStreamStore();
  const [isMicEnabled, setIsMicEnabled] = useState(true);
  const [isCameraEnabled, setIsCameraEnabled] = useState(true);
  const [isEnded, setIsEnded] = useState<boolean>();
  const [, setEndAt] = useState<Date>();
  const fullscreenRef = useRef(null);
  const [isFullscreen, { toggleFullscreen }] = useFullscreen(fullscreenRef);
  const [isVideoInitialized, setIsVideoInitialized] = useState<boolean>(false);
  const [step, setStep] = useState<number>(1);
  const [isShowChat, setIsShowChat] = useState<boolean>(false);
  const { isPortrait } = useMobileOrientation();
  const { setMessages } = useChatStore();

  async function startCall(remotePeerId: string) {
    if (!peerInstance) return;

    console.log("startCall", remotePeerId);

    const options = {
      constraints: {
        offerToReceiveVideo: true,
        offerToReceiveAudio: true,
      },
    };

    const call = peerInstance.call(remotePeerId, localStream, options as any);

    let accept = true;
    call.on("stream", (remoteStream) => {
      if (!accept) return;
      console.log("setRemoteStreams", remoteStream);
      setRemoteStreams((prev) => [
        ...prev,
        { peerId: remotePeerId, mediaStream: remoteStream },
      ]);
      accept = false;
    });
  }

  async function getUserMedia() {
    try {
      const mediaStream = await navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true,
      });

      if (!localVideoRef.current) return;

      localVideoRef.current.srcObject = mediaStream;
      localVideoRef.current.onloadedmetadata = () => {
        localVideoRef.current?.play();
      };

      setLocalStream(mediaStream);
      setPermission(true);
      console.log("setLocalStream mediaStream", mediaStream);
    } catch (error) {
      setPermission(false);
      console.log("ERROR: ", error);
    }
  }

  function initPeer() {
    const peer = new Peer({
      host: "stream.graff.tech",
      config: {
        iceServers: [
          {
            urls: "turn:194.26.138.94:3478", // Replace with your TURN server URL
            username: "username1", // Replace with your TURN username
            credential: "password1", // Replace with your TURN credential
          },
        ],
      },
    });

    peer.on("open", (id) => {
      setPeerId(id);
    });

    peer.on("call", (call) => {
      call.answer(localStream || undefined);

      let accept = true;
      call.on("stream", (remoteStream) => {
        if (!accept) return;
        setRemoteStreams((prev) => [
          ...prev,
          { peerId: call.peer, mediaStream: remoteStream },
        ]);
        accept = false;
      });
    });

    setPeerInstance(peer);
  }

  function initSocket() {
    const superAdmin = searchParams.has("admin", true);

    console.log("superAdmin", superAdmin);

    const socket = io(import.meta.env.VITE_SOCKET_URL, {
      transports: ["websocket"],
      auth: {
        roomId,
        user: {
          id: userId,
          name,
          peerId,
          superAdmin,
        },
      },
    });

    socket.on("update", async (users: IUser[]) => {
      console.log("isCallInit", isCallInit.current);

      if (!isCallInit.current) {
        for (const user of users) {
          if (userId === user.id) continue;

          await startCall(user.peerId);
        }

        isCallInit.current = true;
      }

      setMe(users.find((user) => user.id === userId));
      setUsers(users);
    });

    socket.on("request-control", (userId) => {
      const user = users.find((user) => user.id === userId);

      if (user?.id === me?.id || !me?.isAdmin) return;

      toast.info(`${user?.name} запрашивает разрешение на управление`);
    });

    socket.on("transfer-control", (userId) => {
      if (me?.id !== userId) return;

      toast.info(`Вы получили разрешение на управление`);
    });

    socket.on("message", ({ userId, text }) => {
      setMessages([...useChatStore.getState().messages, { userId, text }]);
    });

    socket.on("connect", () => {
      setSocket(socket);
    });
  }

  function toggleMic() {
    localStream.getAudioTracks().forEach((track) => {
      track.enabled = !track.enabled;

      if (!permission) return;
      setIsMicEnabled(track.enabled);
    });
  }

  function toggleCamera() {
    localStream.getVideoTracks().forEach((track) => {
      track.enabled = !track.enabled;

      if (!permission) return;
      setIsCameraEnabled(track.enabled);
    });
  }

  useEffect(() => {
    if (!socket) return;
    console.log("socket", socket);
  }, [socket?.connected]);

  function updateRemoteStreams() {
    setTimeout(() => {
      console.log("users", users);

      const newRemoteStreams = remoteStreamsRef.current.filter((remoteStream) =>
        users.some((user) => user.peerId === remoteStream.peerId)
      );

      setRemoteStreams(newRemoteStreams);
    }, 500);
  }

  function handleSetName() {
    setStep(2);
    getUserMedia();
  }

  async function getWSUrl() {
    const activeSession = await getActiveSession();

    if (!activeSession || activeSession.status === "error") {
      setIsEnded(true);
      return;
    }

    setIsEnded(false);
    setWSUrl(
      `wss://${activeSession.location}.sess.stream.graff.tech/server/${activeSession.localIP}:${activeSession.cirrusPort}`
    );
    setModal(<SetNameModal onAction={handleSetName} />);

    checkSessionStatus();
  }

  function transferControl(userId: string) {
    socket?.emit("transfer-control", userId);
  }

  function requestControl(userId: string) {
    console.log("requestControl func", userId);
    socket?.emit("request-control", userId);
  }

  async function getActiveSession() {
    const activeSession: any = await api
      .get(`activeSessions/${params.id}`)
      .json();

    if (activeSession?.endAt) {
      setEndAt(activeSession.endAt);
    }

    return activeSession;
  }

  async function checkSessionStatus() {
    const activeSession = await getActiveSession();

    if (!activeSession || activeSession.status === "error") {
      setIsEnded(true);
      return;
    }

    setTimeout(async () => {
      await checkSessionStatus();
    }, 1000);
  }

  useEffect(() => {
    getWSUrl();
    // initSocket();
  }, []);

  useEffect(() => {
    if (permission === undefined) return;

    initPeer();
  }, [permission]);

  useEffect(() => {
    if (step !== 2) return;

    if (!isVideoInitialized) {
      setModal(<LoadingModal />);
    } else {
      setModal(null);
    }
  }, [step, isVideoInitialized]);

  useEffect(() => {
    if (!peerId) return;

    initSocket();
  }, [peerId]);

  useEffect(() => {
    if (!users.length) return;

    updateRemoteStreams();
  }, [users.length]);

  return (
    <div
      ref={fullscreenRef}
      className="h-[100dvh] flex lg:flex-col bg-[#111C26] overflow-hidden"
    >
      {isEnded === false && (
        <>
          <div className="flex items-center justify-between w-12 bg-white max-lg:flex-col lg:h-12 lg:w-auto lg:px-6 max-lg:py-2">
            <div className="lg:pr-6">
              <img
                src="/images/logo24.svg"
                alt=""
                className="hidden lg:block"
              />
            </div>
            <div className="flex items-center gap-4">
              <div className="items-center hidden gap-2 lg:flex">
                <div className="relative w-6 h-6 bg-[#E6ECF2] rounded-full flex items-center justify-center">
                  <p className="text-xs font-semibold">
                    {name[0]?.toUpperCase()}
                  </p>
                  {me?.isControlAllowed && (
                    <div className="absolute bottom-0 right-0 bg-[#49A1F5] w-2 h-2 rounded-full border border-white"></div>
                  )}
                </div>
                <p className="text-xs">{name}</p>
                <div className="text-[#CCCCCC]">
                  {isMobile ? <MobileIcon /> : <DesktopIcon />}
                </div>
              </div>
              <div className="flex items-center gap-2 max-lg:flex-col">
                <div className="relative group">
                  <Button
                    variant="secondary"
                    icon={
                      me?.isControlAllowed ? <HandOnIcon /> : <HandOffIcon />
                    }
                    onlyIcon
                    onClick={() =>
                      me!.isAdmin
                        ? transferControl(me!.id)
                        : requestControl(me!.id)
                    }
                  />
                  {me?.isAdmin && !me.isControlAllowed && (
                    <Tooltip text={"Вернуть управление"} />
                  )}

                  {!me?.isAdmin && !me?.isControlAllowed && (
                    <Tooltip text={"Запросить управление"} />
                  )}
                </div>

                {permission && (
                  <>
                    <div className="relative group">
                      <Button
                        variant="secondary"
                        icon={isMicEnabled ? <MicroOnIcon /> : <MicroOffIcon />}
                        onlyIcon
                        onClick={toggleMic}
                      />
                      <Tooltip
                        text={
                          isMicEnabled
                            ? "Выключить микрофон"
                            : "Включить микрофон"
                        }
                      />
                    </div>
                    <div className="relative group">
                      <Button
                        variant="secondary"
                        icon={
                          isCameraEnabled ? <CameraOnIcon /> : <CameraOffIcon />
                        }
                        onlyIcon
                        onClick={toggleCamera}
                      />
                      <Tooltip
                        text={
                          isCameraEnabled
                            ? "Выключить камеру"
                            : "Включить камеру"
                        }
                      />
                    </div>
                  </>
                )}
              </div>
              <div className="h-4 w-px bg-[#DAE0E5] lg:block hidden"></div>
              <div className="hidden gap-6 lg:flex">
                {users.map((user) => {
                  if (user.id !== userId) {
                    return (
                      <div key={user.id} className="flex items-center gap-2">
                        <div className="relative w-6 h-6 bg-[#E6ECF2] rounded-full flex items-center justify-center">
                          <p className="text-xs font-semibold">
                            {name[0]?.toUpperCase()}
                          </p>
                          {user?.isControlAllowed && (
                            <div className="absolute bottom-0 right-0 bg-[#49A1F5] w-2 h-2 rounded-full border border-white"></div>
                          )}
                        </div>
                        <p className="text-xs">{user.name}</p>
                        <div className="text-[#CCCCCC]">
                          {isMobile ? <MobileIcon /> : <DesktopIcon />}
                        </div>

                        {me?.isAdmin && me?.isControlAllowed && (
                          <div className="relative">
                            {/* <Button
                        variant="secondary"
                        icon={<MoreIcon />}
                        onlyIcon
                      /> */}
                            {/* <div className="absolute"> */}
                            <div className="relative group">
                              <Button
                                variant="secondary"
                                icon={<HandOnIcon />}
                                onlyIcon
                                onClick={() => transferControl(user.id)}
                              />
                              <Tooltip text={"Передать управление"} />
                            </div>
                            {/* </div> */}
                          </div>
                        )}
                      </div>
                    );
                  }
                })}
              </div>
            </div>
            <div className="flex gap-2 max-lg:flex-col lg:ml-auto">
              <div className="relative group">
                <Button
                  variant="secondary"
                  icon={<ChatIcon />}
                  onlyIcon
                  onClick={() => setIsShowChat((prev) => !prev)}
                />
                <Tooltip text={isShowChat ? "Скрыть чат" : "Показать чат"} />
              </div>
              <div className="relative group">
                <Button
                  variant="secondary"
                  icon={<ShareIcon />}
                  onlyIcon
                  onClick={() => setModal(<InviteModal />)}
                />
                <Tooltip text={"Поделиться"} />
              </div>
              {!isIOS && (
                <div className="relative group">
                  <Button
                    variant="secondary"
                    icon={isFullscreen ? <WindowIcon /> : <FullscreenIcon />}
                    onlyIcon
                    onClick={toggleFullscreen}
                  />
                  <Tooltip
                    text={
                      isFullscreen ? "Оконный режим" : "Полноэкранный режим"
                    }
                  />
                </div>
              )}
            </div>
          </div>
          <div className="relative flex flex-1">
            {WSUrl && (
              <PixelStreamingWrapper2
                initialSettings={{
                  AutoPlayVideo: true,
                  AutoConnect: true,
                  ss: WSUrl,
                  StartVideoMuted: true,
                  HoveringMouse: true,
                  WaitForStreamer: true,
                }}
                onVideoInitialized={() => setIsVideoInitialized(true)}
              />
            )}

            {step !== 1 &&
              !users.find((user) => user.id === userId)?.isControlAllowed && (
                <div
                  className="absolute top-0 left-0 w-full h-full"
                  onClick={() =>
                    toast.warn("Необходимо запросить разрешение на управление")
                  }
                ></div>
              )}

            <Draggable
              defaultClassName="cursor-grab"
              defaultClassNameDragging="cursor-grabbing"
            >
              <div className="absolute space-y-2 top-2 lg:left-2 max-lg:right-2">
                <div className={`relative ${!permission ? "hidden" : ""}`}>
                  <video
                    ref={localVideoRef}
                    className={`aspect-video lg:w-[216px] w-[160px] lg:h-[162px] h-[120px] rounded-lg object-cover bg-gray-500 -scale-x-100 ring-2 ${
                      isMicEnabled && isSpeaking
                        ? "ring-green-500"
                        : "ring-transparent"
                    }`}
                    playsInline
                    autoPlay
                    muted
                  ></video>
                  <div className="absolute bottom-0 p-2">
                    <p className="text-sm text-white">{name}</p>
                  </div>
                </div>
                {remoteStreams.map(({ peerId, mediaStream }) => (
                  <Video
                    key={peerId}
                    mediaStream={mediaStream}
                    muted={!permission}
                    user={users.find((user) => user.peerId === peerId)}
                  />
                ))}
              </div>
            </Draggable>

            {isShowChat && <Chat2 onClose={() => setIsShowChat(false)} />}
          </div>

          {isPortrait && (
            <div className="absolute top-0 left-0 flex flex-col items-center justify-center w-full h-full gap-2 bg-white">
              <Rotate64Icon />
              <p className="font-semibold">Поверните устройство</p>
            </div>
          )}

          <ModalContainer2 />
          <ToastContainer />
        </>
      )}

      {isEnded === true && (
        <div className="flex items-center justify-center flex-1 p-8">
          <p className="text-2xl text-center text-white font-gilroy">
            <Trans i18nKey={"demonstrationCompleted"}>
              Данная демонстрация была завершена
            </Trans>
          </p>
        </div>
      )}
    </div>
  );
}

export default StreamPage3;
