/* 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 User from "../components/User";
// import ChatIcon from "../components/icons/ChatIcon";

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

const userId = uuidv4();

function StreamPage() {
  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("kick", (userId) => {
      if (useStreamUserStore.getState().me?.id !== userId) return;

      window.close();
      socket.disconnect();
      setPeerInstance(undefined);
      setWSUrl("");
      setUsers([]);
      setRemoteStreams([]);
    });

    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) {
    socket?.emit("request-control", userId);
  }

  function kick(userId: string) {
    socket?.emit("kick", 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]);

  useEffect(() => {
    toggleCamera();
    toggleMic();
  }, [localStream]);

  return (
    <div
      ref={fullscreenRef}
      className="h-dvh flex lg:flex-col bg-[#111C26] overflow-hidden"
    >
      {isEnded === false && (
        <>
          {me && (
            <>
              <div
                className={`flex items-center justify-between ${
                  isFullscreen ? "fixed z-10 top-2 min-w-[744px] rounded-lg left-1/2 -translate-x-1/2" : ""
                } 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">
                    {me &&
                      users.map((user) => {
                        if (user.id !== userId) {
                          return (
                            <User
                              me={me}
                              user={user}
                              handleTransferControl={() =>
                                transferControl(user.id)
                              }
                              handleKick={() => kick(user.id)}
                            />
                          );
                        }
                      })}
                  </div>
                </div>
                <div className="flex items-center gap-2 lg:gap-4 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="w-px h-4 bg-[#DAE0E5] max-lg:hidden"></div>
                  <div className="flex gap-2 max-lg:flex-col lg:ml-auto">
                    <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>
            </>
          )}
          <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 isFullscreen={isFullscreen} 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 StreamPage;
