/* eslint-disable no-irregular-whitespace */
/* eslint-disable react-hooks/exhaustive-deps */
/* eslint-disable @typescript-eslint/no-explicit-any */
import { useParams, useSearchParams } from "react-router-dom";
import { FullScreen, useFullScreenHandle } from "react-full-screen";
import { useEffect, useRef, useState } from "react";
import ky from "ky";
import { Socket, io } from "socket.io-client";
import userAgentParser from "ua-parser-js";
import { Player } from "./components/Player";
import { Trans, useTranslation } from "react-i18next";
import ShareIcon from "./components/icons/ShareIcon";
import ModalContainer from "./components/ModalContainer";
import useModalStore from "./stores/useModalStore";
import ShareModal from "./components/modals/ShareModal";
import { Transition } from "react-transition-group";
import FullscreenIcon from "./components/icons/FullscreenIcon";
import WindowedModeIcon from "./components/icons/WindowedModeIcon";
import QRIcon from "./components/icons/QRIcon";
import QRCodeModal from "./components/modals/QRCodeModal";
import PersonsIcon from "./components/icons/PersonsIcon";
import UsersManagementModal from "./components/modals/UsersManagementModal";
import useStreamUserStore from "./stores/useStreamUserStore";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
// import UserIcon from "./components/icons/UserIcon";
// import HandOnIcon from "./components/icons/HandOnIcon";
import AlertIcon from "./components/icons/AlertIcon";
import useSocketStore from "./stores/useSocketStore";
import { LiveKitRoom, RoomAudioRenderer } from "@livekit/components-react";
import ToggleMic from "./components/ToggleMic";
import Chat from "./components/Chat";
// import AFKTimerModal from "./components/modals/AFKTimerModal";
import { differenceInMilliseconds, format, parseISO } from "date-fns";
import HandOnIcon from "./components/icons/HandOnIcon";
import { useMobileOrientation } from "react-device-detect";
import RotateDeviceIcon from "./components/icons/RotateDeviceIcon";

function StreamPage() {
  const { t } = useTranslation();
  const handleFullScreen = useFullScreenHandle();
  const [streamUrl, setStreamUrl] = useState<string>("");
  const [isStreamEnded, setIsStreamEnded] = useState<boolean>(false);
  const [isStreamLoaded, setStreamLoaded] = useState<boolean>(false);
  const [me, setMe] = useState<any>({});
  const meRef = useRef<any>({});
  meRef.current = me;
  const [modal, setModal] = useModalStore((state) => [
    state.modal,
    state.setModal,
  ]);
  const params = useParams();
  const [searchParams] = useSearchParams();
  const roomId = params.id;
  const livekitServerUrl = "wss://livekit.stream.graff.tech";
  const [token, setToken] = useState<string>();
  const [socket, setSocket] = useSocketStore((state) => [
    state.socket,
    state.setSocket,
  ]);
  const [users, setUsers] = useStreamUserStore((state) => [
    state.users,
    state.setUsers,
  ]);
  const [isShowChat, setIsShowChat] = useState<boolean>(false);
  const [stopwatch, setStopwatch] = useState<string>();
  const { orientation } = useMobileOrientation();

  async function getToken() {
    if (!socket) return;

    const { token }: any = await ky
      .get(
        `https://coord.graff.tech/getToken?roomName=${roomId}&participantName=${socket.id}`
      )
      .json();

    setToken(token);
  }

  function updateStartDate(date: Date) {
    const diffMs = differenceInMilliseconds(new Date(), date);
    setStopwatch(format(diffMs, "mm:ss"));

    setTimeout(() => {
      updateStartDate(date);
    }, 1000);
  }

  async function connect() {
    const activeSession: any = await ky
      .get(`${import.meta.env.VITE_COORD_URL}/active_sessions/${params.id}`)
      .json();

    if (activeSession) {
      setStreamUrl(
        `wss://${activeSession.location}.sess.stream.graff.tech/${activeSession.server}/${activeSession.cirrusPort}/`
      );

      updateStartDate(parseISO(activeSession.createdAt));

      setStreamLoaded(true);
    } else {
      setIsStreamEnded(true);
    }
  }

  function update(socketId: string, data: { [key: string]: any }) {
    if (!socket) return;

    socket.emit("update", socketId, data);
  }

  function kick(socketId: string) {
    if (!socket) return;

    socket.emit("kick", socketId);
  }

  function toastWarn(text: string) {
    toast.warn(text, {
      position: "top-center",
      autoClose: 2000,
      hideProgressBar: true,
      closeOnClick: true,
      pauseOnHover: true,
      draggable: true,
      theme: "dark",
      icon: <AlertIcon />,
      closeButton: false,
    });
  }

  // function toastUser(text: string) {
  //   toast.info(text, {
  //     position: "top-center",
  //     autoClose: 2000,
  //     hideProgressBar: true,
  //     closeOnClick: true,
  //     pauseOnHover: true,
  //     draggable: true,
  //     theme: "dark",
  //     icon: <UserIcon />,
  //     closeButton: false,
  //   });
  // }

  function toastHandOn(text: string) {
    toast.info(text, {
      position: "top-center",
      autoClose: 2000,
      hideProgressBar: true,
      closeOnClick: true,
      pauseOnHover: true,
      draggable: true,
      theme: "dark",
      icon: <HandOnIcon />,
      closeButton: false,
    });
  }

  async function checkIsActiveSession() {
    const activeSession: any = await ky
      .get(`${import.meta.env.VITE_COORD_URL}/active_sessions/${params.id}`)
      .json();

    if (!activeSession) {
      setIsStreamEnded(true);
      return;
    }

    if (!isStreamEnded) {
      setTimeout(() => {
        checkIsActiveSession();
      }, 1000);
    }
  }

  useEffect(() => {
    connect();

    const socket: Socket = io(import.meta.env.VITE_COORD_URL, {
      query: {
        roomId,
        admin: searchParams.has("admin", "true"),
      },
    });

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

    socket.on("join", (_socketId, sockets) => {
      setUsers(sockets);
      toastHandOn(t("notification.newMember"));
    });

    socket.on("update", (_socketId, _data, sockets) => {
      setUsers(sockets);
    });

    socket.on("kick", () => {
      socket.close();
      window.close();
    });

    socket.on("leave", (socketId) => {
      setUsers(
        useStreamUserStore
          .getState()
          .users.filter((user: any) => user.id !== socketId)
      );
    });

    socket.on("notification", (type) => {
      if (type === "afk-timer") {
        // setModal(<AFKTimerModal />);
      }
    });

    checkIsActiveSession();

    return () => {
      socket.off("connect");
      socket.off("join");
      socket.off("update");
      socket.off("kick");
      socket.off("leave");
      socket.close();
    };
  }, []);

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

    getToken();
  }, [socket]);

  useEffect(() => {
    if (socket) {
      setMe(users.find((user: any) => user.id === socket.id));
    }
  }, [users]);

  useEffect(() => {
    if (me && me.allowControl && !me.admin) {
      toastHandOn(t("notification.controlReceived"));
    }
  }, [me]);

  return (
    <FullScreen handle={handleFullScreen} className="h-screen text-[#F2F2F2]">
      {!isStreamEnded ? (
        isStreamLoaded ? (
          <>
            {orientation === "landscape" ? (
              <>{streamUrl && <Player ss={streamUrl} />}</>
            ) : (
              <div className="absolute top-0 left-0 w-full h-full flex flex-col justify-center items-center gap-2">
                <RotateDeviceIcon />
                <Trans i18nKey="rotateDevice">Поверните устройство</Trans>
              </div>
            )}
          </>
        ) : (
          <div className="absolute top-0 left-0 w-full h-full flex justify-center items-center gap-4">
            <p className="flex items-center gap-4">
              <img
                src="/icons/Loader.png"
                alt=""
                className="animate-spin w-6 h-6"
              />
              <Trans i18nKey="streamWaiting">Ожидание потока</Trans>
            </p>
          </div>
        )
      ) : (
        <div className="absolute top-0 left-0 w-full h-full flex justify-center items-center">
          <p className="text-2xl font-gilroy">
            <Trans i18nKey="streamEnded">Трансляция была завершена</Trans>
          </p>
        </div>
      )}

      {me && !me.allowControl && (
        <>
          {new userAgentParser(me.ua).getDevice().type === "mobile" ? (
            <div
              className="absolute top-0 left-0 w-full h-full"
              onTouchStart={() => toastWarn(t("notification.getAccess"))}
            ></div>
          ) : (
            <div
              className="absolute top-0 left-0 w-full h-full"
              onMouseDown={() => toastWarn(t("notification.getAccess"))}
            ></div>
          )}
        </>
      )}

      <div className="absolute top-0 left-0 min-h-screen flex flex-col justify-center transition-all">
        <div className="flex flex-col gap-4 lg:p-4 p-2">
          {new userAgentParser().getDevice().model !== "iPhone" && (
            <>
              {!handleFullScreen.active ? (
                <button
                  onClick={() => handleFullScreen.enter()}
                  className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
                >
                  <FullscreenIcon />
                  <span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
                    <Trans i18nKey={"fullscreenMode"}>
                      Полноэкранный режим
                    </Trans>
                  </span>
                </button>
              ) : (
                <button
                  onClick={() => handleFullScreen.exit()}
                  className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
                >
                  <WindowedModeIcon />
                  <span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
                    <Trans i18nKey={"windowedMode"}>Оконный режим</Trans>
                  </span>
                </button>
              )}
            </>
          )}

          <button
            onClick={() => setModal(<QRCodeModal />)}
            className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
          >
            <QRIcon />
            <span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
              <Trans i18nKey={"inviteByQRCode"}>Пригласить по QR коду</Trans>
            </span>
          </button>

          <button
            onClick={() => setModal(<ShareModal />)}
            className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
          >
            <ShareIcon />
            <span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
              <Trans i18nKey={"inviteByLink"}>Пригласить по ссылке</Trans>
            </span>
          </button>

          <button
            onClick={() =>
              setModal(
                <UsersManagementModal
                  me={me}
                  handleUpdate={update}
                  handleKick={kick}
                />
              )
            }
            className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90"
          >
            <PersonsIcon />
            <span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
              <Trans i18nKey={"members"}>Участники</Trans>
            </span>
            <div className="absolute px-2 py-1 text-xs flex flex-col justify-center items-center rounded-full -top-2 -right-2  bg-[#131313] -z-10">
              {users.length}
            </div>
          </button>

          {/* <button
            onClick={() => setIsShowChat(true)}
            className="relative group outline-none bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90 flex justify-center items-center"
          >
            <ChatIcon className="w-5 h-5" />
            <span className="absolute left-12 top-[50%] -translate-y-[50%] invisible group-hover:visible opacity-0 group-hover:opacity-100 text-xs transition-all px-2 py-1 bg-[#131313] rounded">
              <Trans i18nKey={"chat"}>Чат</Trans>
            </span>
          </button> */}

          <LiveKitRoom
            video={false}
            audio={true}
            token={token}
            serverUrl={livekitServerUrl}
          >
            <RoomAudioRenderer />
            <ToggleMic socket={socket} handleUpdate={update} />
          </LiveKitRoom>

          <div className="relative group outline-none w-10 h-10 bg-[#131313] rounded-full shadow-lg shadow-[#131313] p-2 opacity-90 flex justify-center items-center">
            <p className="text-xs">{stopwatch}</p>
          </div>
        </div>
      </div>

      <Transition in={isShowChat} timeout={200} mountOnEnter unmountOnExit>
        {(state) => (
          <div className="absolute right-0 bottom-0">
            <Chat className={state} handleClose={() => setIsShowChat(false)} />
          </div>
        )}
      </Transition>

      <Transition
        in={modal ? true : false}
        timeout={200}
        mountOnEnter
        unmountOnExit
      >
        {(state) => <ModalContainer className={state} />}
      </Transition>

      <ToastContainer />
    </FullScreen>
  );
}

export default StreamPage;
