import {
  Box,
  FormControl,
  IconButton,
  InputAdornment,
  InputBase,
  SxProps,
  Theme,
  Typography,
  useMediaQuery,
  useTheme,
} from "@mui/material";
import {
  TicketMessage,
  makeRequest,
  useTicketsFetcher,
  useTicketMessages,
  getMessageFromFetchError,
  useSSESubscription,
  useEventListener,
  createTicket,
} from "@frontend/kitui";
import { enqueueSnackbar } from "notistack";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import ChatMessage from "../ChatMessage";
import SendIcon from "../icons/SendIcon";
import UserCircleIcon from "./UserCircleIcon";
import { throttle } from "@frontend/kitui";
import { sendTicketMessage, shownMessage } from "@root/api/ticket";
import { useSSETab } from "@root/utils/hooks/useSSETab";
import {
  checkAcceptableMediaType,
  MAX_FILE_SIZE,
  ACCEPT_SEND_MEDIA_TYPES_MAP,
} from "@utils/checkAcceptableMediaType";
import {
  useTicketStore,
  setTicketData,
  addOrUpdateUnauthMessages,
  setUnauthTicketMessageFetchState,
  setUnauthIsPreventAutoscroll,
  incrementUnauthMessageApiPage,
  setIsMessageSending,
} from "@root/stores/tickets";
import { useUserStore } from "@root/stores/user";
import AttachFileIcon from "@mui/icons-material/AttachFile";
import ChatDocument from "./ChatDocument";
import ChatImage from "./ChatImage";
import ChatVideo from "./ChatVideo";

type ModalWarningType =
  | "errorType"
  | "errorSize"
  | "picture"
  | "video"
  | "audio"
  | "document"
  | null;
interface Props {
  open: boolean;
  sx?: SxProps<Theme>;
}

export default function Chat({ open = false, sx }: Props) {
  const theme = useTheme();
  const upMd = useMediaQuery(theme.breakpoints.up("md"));
  const [messageField, setMessageField] = useState<string>("");
  const [disableFileButton, setDisableFileButton] = useState(false);
  const [modalWarningType, setModalWarningType] =
    useState<ModalWarningType>(null);
  const chatBoxRef = useRef<HTMLDivElement>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const user = useUserStore((state) => state.user?._id);
  const ticket = useTicketStore(
    (state) => state[user ? "authData" : "unauthData"]
  );
  const {
    messages,
    sessionData,
    isMessageSending,
    isPreventAutoscroll,
    lastMessageId,
    messagesPerPage,
    unauthTicketMessageFetchState: fetchState,
    apiPage: messageApiPage,
  } = ticket;

  const { isActiveSSETab, updateSSEValue } = useSSETab<TicketMessage[]>(
    "ticket",
    addOrUpdateUnauthMessages
  );

  useTicketMessages({
    url: process.env.REACT_APP_DOMAIN + "/heruvym/getMessages",
    isUnauth: true,
    ticketId: sessionData?.ticketId,
    messagesPerPage,
    messageApiPage,
    onSuccess: useCallback((messages) => {
      if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1) {
        chatBoxRef.current.scrollTop = 1;
      }

      addOrUpdateUnauthMessages(messages);
    }, []),
    onError: useCallback((error: Error) => {
      const message = getMessageFromFetchError(error);
      if (message) enqueueSnackbar(message);
    }, []),
    onFetchStateChange: setUnauthTicketMessageFetchState,
  });

  useSSESubscription<TicketMessage>({
    enabled: isActiveSSETab && Boolean(sessionData),
    url:
      process.env.REACT_APP_DOMAIN +
      `/heruvym/ticket?ticket=${sessionData?.ticketId}&s=${sessionData?.sessionId}`,
    onNewData: (ticketMessages) => {
      updateSSEValue(ticketMessages);

      addOrUpdateUnauthMessages(ticketMessages);
    },
    onDisconnect: useCallback(() => {
      setUnauthIsPreventAutoscroll(false);
    }, []),
    marker: "ticket",
  });

  useTicketsFetcher({
    url: process.env.REACT_APP_DOMAIN + "/heruvym/getTickets",
    ticketsPerPage: 10,
    ticketApiPage: 0,
    onSuccess: (result) => {
      if (result.data?.length) {
        const currentTicket = result.data.find(
          ({ origin }) => !origin.includes("/support")
        );

        if (!currentTicket) {
          return;
        }

        setTicketData({
          ticketId: currentTicket.id,
          sessionId: currentTicket.sess,
        });
      }
    },
    onError: (error: Error) => {
      const message = getMessageFromFetchError(error);
      if (message) enqueueSnackbar(message);
    },
    onFetchStateChange: () => {},
    enabled: Boolean(user),
  });

  const throttledScrollHandler = useMemo(
    () =>
      throttle(() => {
        const chatBox = chatBoxRef.current;
        if (!chatBox) return;

        const scrollBottom =
          chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight;
        const isPreventAutoscroll = scrollBottom > chatBox.clientHeight;
        setUnauthIsPreventAutoscroll(isPreventAutoscroll);

        if (fetchState !== "idle") return;

        if (chatBox.scrollTop < chatBox.clientHeight) {
          incrementUnauthMessageApiPage();
        }
      }, 200),
    [fetchState]
  );

  useEventListener("scroll", throttledScrollHandler, chatBoxRef);

  useEffect(
    function scrollOnNewMessage() {
      if (!chatBoxRef.current) return;

      if (!isPreventAutoscroll) {
        setTimeout(() => {
          scrollToBottom();
        }, 50);
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    },
    [lastMessageId]
  );

  useEffect(() => {
    if (open) {
      const newMessages = messages.filter(({ shown }) => shown.me !== 1);

      newMessages.map(async ({ id }) => {
        await shownMessage(id);
      });
    }
  }, [open, messages]);

  async function handleSendMessage() {
    if (!messageField || isMessageSending) return;

    if (!sessionData?.ticketId) {
      setIsMessageSending(true);
      createTicket({
        url: process.env.REACT_APP_DOMAIN + "/heruvym/create",
        body: {
          Title: "Unauth title",
          Message: messageField,
        },
        useToken: Boolean(user),
      })
        .then((response) => {
          setTicketData({
            ticketId: response.Ticket,
            sessionId: response.sess,
          });
        })
        .catch((error) => {
          const errorMessage = getMessageFromFetchError(error);
          if (errorMessage) enqueueSnackbar(errorMessage);
        })
        .finally(() => {
          setMessageField("");
          setIsMessageSending(false);
        });
    } else {
      setIsMessageSending(true);

      const [_, sendTicketMessageError] = await sendTicketMessage(
        sessionData.ticketId,
        messageField
      );

      if (sendTicketMessageError) {
        enqueueSnackbar(sendTicketMessageError);
      }

      setMessageField("");
      setIsMessageSending(false);
    }
  }

  function scrollToBottom(behavior?: ScrollBehavior) {
    if (!chatBoxRef.current) return;

    const chatBox = chatBoxRef.current;
    chatBox.scroll({
      left: 0,
      top: chatBox.scrollHeight,
      behavior,
    });
  }

  const handleTextfieldKeyPress: React.KeyboardEventHandler<
    HTMLInputElement | HTMLTextAreaElement
  > = (e) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      handleSendMessage();
    }
  };

  const sendFile = async (file: File) => {
    if (file === undefined) return true;

    console.log("тут ошибка", modalWarningType);
    let data;
    if (!ticket.sessionData?.ticketId) {
      try {
        data = await createTicket({
          url: process.env.REACT_APP_DOMAIN + "/heruvym/create",
          body: {
            Title: "Unauth title",
            Message: "",
          },
          useToken: Boolean(user),
        });
        setTicketData({
          ticketId: data.Ticket,
          sessionId: data.sess,
        });
      } catch (error: any) {
        const errorMessage = getMessageFromFetchError(error);
        if (errorMessage) enqueueSnackbar(errorMessage);
      }
      setIsMessageSending(false);
    }

    const ticketId = ticket.sessionData?.ticketId || data?.Ticket;
    if (ticketId !== undefined) {
      if (file.size > MAX_FILE_SIZE) return setModalWarningType("errorSize");
      try {
        const body = new FormData();

        body.append(file.name, file);
        body.append("ticket", ticketId);
        await makeRequest({
          url: process.env.REACT_APP_DOMAIN + "/heruvym/sendFiles",
          body: body,
          method: "POST",
        });
      } catch (error: any) {
        const errorMessage = getMessageFromFetchError(error);
        if (errorMessage) enqueueSnackbar(errorMessage);
      }
      return true;
    }
  };

  const sendFileHC = async (file: File) => {
    console.log(file);
    const check = checkAcceptableMediaType(file);
    if (check.length > 0) {
      enqueueSnackbar(check);
      return;
    }
    setDisableFileButton(true);
    await sendFile(file);
    setDisableFileButton(false);
    console.log(disableFileButton);
  };

  return (
    <>
      {open && (
        <Box
          sx={{
            display: "flex",
            flexDirection: "column",
            height: "clamp(250px, calc(100vh - 90px), 600px)",
            backgroundColor: "#944FEE",
            borderRadius: "8px",
            ...sx,
          }}
        >
          <Box
            sx={{
              display: "flex",
              gap: "9px",
              pl: "22px",
              pt: "12px",
              pb: "20px",
              filter: "drop-shadow(0px 3px 12px rgba(37, 39, 52, 0.3))",
            }}
          >
            <UserCircleIcon />
            <Box
              sx={{
                mt: "5px",
                display: "flex",
                flexDirection: "column",
                gap: "3px",
              }}
            >
              <Typography>Мария</Typography>
              <Typography
                sx={{
                  fontSize: "16px",
                  lineHeight: "19px",
                }}
              >
                онлайн-консультант
              </Typography>
            </Box>
          </Box>
          <Box
            sx={{
              flexGrow: 1,
              backgroundColor: "white",
              borderRadius: "8px",
              display: "flex",
              flexDirection: "column",
            }}
          >
            <Box
              ref={chatBoxRef}
              sx={{
                display: "flex",
                width: "100%",
                flexBasis: 0,
                flexDirection: "column",
                gap: upMd ? "20px" : "16px",
                px: upMd ? "20px" : "5px",
                py: upMd ? "20px" : "13px",
                overflowY: "auto",
                flexGrow: 1,
              }}
            >
              {ticket.sessionData?.ticketId &&
                messages.map((message) => {
                  const isFileVideo = () => {
                    if (message.files) {
                      return ACCEPT_SEND_MEDIA_TYPES_MAP.video.some(
                        (fileType) =>
                          message.files[0].toLowerCase().endsWith(fileType)
                      );
                    }
                  };
                  const isFileImage = () => {
                    if (message.files) {
                      return ACCEPT_SEND_MEDIA_TYPES_MAP.picture.some(
                        (fileType) =>
                          message.files[0].toLowerCase().endsWith(fileType)
                      );
                    }
                  };
                  const isFileDocument = () => {
                    if (message.files) {
                      return ACCEPT_SEND_MEDIA_TYPES_MAP.document.some(
                        (fileType) =>
                          message.files[0].toLowerCase().endsWith(fileType)
                      );
                    }
                  };
                  if (message.files.length > 0 && isFileImage()) {
                    return (
                      <ChatImage
                        unAuthenticated
                        key={message.id}
                        file={message.files[0]}
                        createdAt={message.created_at}
                        isSelf={
                          (ticket.sessionData?.sessionId || user) ===
                          message.user_id
                        }
                      />
                    );
                  }
                  if (message.files.length > 0 && isFileVideo()) {
                    return (
                      <ChatVideo
                        unAuthenticated
                        key={message.id}
                        file={message.files[0]}
                        createdAt={message.created_at}
                        isSelf={
                          (ticket.sessionData?.sessionId || user) ===
                          message.user_id
                        }
                      />
                    );
                  }
                  if (message.files.length > 0 && isFileDocument()) {
                    return (
                      <ChatDocument
                        unAuthenticated
                        key={message.id}
                        file={message.files[0]}
                        createdAt={message.created_at}
                        isSelf={
                          (ticket.sessionData?.sessionId || user) ===
                          message.user_id
                        }
                      />
                    );
                  }
                  return (
                    <ChatMessage
                      unAuthenticated
                      key={message.id}
                      text={message.message}
                      createdAt={message.created_at}
                      isSelf={
                        (ticket.sessionData?.sessionId || user) ===
                        message.user_id
                      }
                    />
                  );
                })}
            </Box>
            <FormControl fullWidth sx={{ borderTop: "1px solid black" }}>
              <InputBase
                value={messageField}
                fullWidth
                placeholder="Введите сообщение..."
                id="message"
                multiline
                onKeyDown={handleTextfieldKeyPress}
                sx={{
                  width: "100%",
                  p: 0,
                }}
                inputProps={{
                  sx: {
                    fontWeight: 400,
                    fontSize: "16px",
                    lineHeight: "19px",
                    pt: upMd ? "30px" : "28px",
                    pb: upMd ? "30px" : "24px",
                    px: "19px",
                    maxHeight: "calc(19px * 5)",
                    color: "black",
                  },
                }}
                onChange={(e) => setMessageField(e.target.value)}
                endAdornment={
                  <InputAdornment position="end">
                    <IconButton
                      disabled={disableFileButton}
                      onClick={() => {
                        console.log(disableFileButton);
                        if (!disableFileButton) fileInputRef.current?.click();
                      }}
                    >
                      <AttachFileIcon />
                    </IconButton>
                    <input
                      ref={fileInputRef}
                      id="fileinput"
                      onChange={({ target }) => {
                        if (target.files?.[0]) {
                          sendFileHC(target.files?.[0]);
                        }
                      }}
                      style={{ display: "none" }}
                      type="file"
                    />
                    <IconButton
                      disabled={isMessageSending}
                      onClick={handleSendMessage}
                      sx={{
                        height: "53px",
                        width: "53px",
                        mr: "13px",
                        p: 0,
                        opacity: isMessageSending ? 0.3 : 1,
                      }}
                    >
                      <SendIcon
                        style={{
                          width: "100%",
                          height: "100%",
                        }}
                      />
                    </IconButton>
                  </InputAdornment>
                }
              />
            </FormControl>
          </Box>
        </Box>
      )}
    </>
  );
}
