import {
  Box,
  Button,
  Fab,
  FormControl,
  IconButton,
  InputAdornment,
  InputBase,
  Typography,
  useMediaQuery,
  useTheme,
} from "@mui/material";
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import SendIcon from "@components/icons/SendIcon";
import { makeRequest, throttle, useToken } from "@frontend/kitui";
import { enqueueSnackbar } from "notistack";
import { useTicketStore } from "@root/stores/tickets";
import {
  addOrUpdateMessages,
  clearMessageState,
  incrementMessageApiPage,
  setIsPreventAutoscroll,
  setTicketMessageFetchState,
  useMessageStore,
} from "@root/stores/messages";
import { TicketMessage } from "@frontend/kitui";
import ChatMessage from "@root/components/ChatMessage";
import { cardShadow } from "@root/utils/theme";
import {
  getMessageFromFetchError,
  useEventListener,
  useSSESubscription,
  useTicketMessages,
} from "@frontend/kitui";
import { shownMessage, sendTicketMessage } from "@root/api/ticket";
import { withErrorBoundary } from "react-error-boundary";
import { handleComponentError } from "@root/utils/handleComponentError";
import { useSSETab } from "@root/utils/hooks/useSSETab";
import {
  checkAcceptableMediaType,
  MAX_FILE_SIZE,
  ACCEPT_SEND_MEDIA_TYPES_MAP,
} from "@utils/checkAcceptableMediaType";
import AttachFileIcon from "@mui/icons-material/AttachFile";
import ChatDocument from "@components/FloatingSupportChat/ChatDocument";
import ChatImage from "@components/FloatingSupportChat/ChatImage";
import ChatVideo from "@components/FloatingSupportChat/ChatVideo";

function SupportChat() {
  console.log("сапортчат отрисовался");
  const theme = useTheme();
  const upMd = useMediaQuery(theme.breakpoints.up("md"));
  const isMobile = useMediaQuery(theme.breakpoints.up(460));
  const [messageField, setMessageField] = useState<string>("");
  const tickets = useTicketStore((state) => state.tickets);
  const messages = useMessageStore((state) => state.messages);
  const messageApiPage = useMessageStore((state) => state.apiPage);
  const lastMessageId = useMessageStore((state) => state.lastMessageId);
  const messagesPerPage = useMessageStore((state) => state.messagesPerPage);
  const isPreventAutoscroll = useMessageStore(
    (state) => state.isPreventAutoscroll
  );
  const [disableFileButton, setDisableFileButton] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const token = useToken();
  const ticketId = useParams().ticketId;
  const ticket = tickets.find((ticket) => ticket.id === ticketId);
  const chatBoxRef = useRef<HTMLDivElement>(null);
  const fetchState = useMessageStore((state) => state.ticketMessageFetchState);
  const { isActiveSSETab, updateSSEValue } = useSSETab<TicketMessage[]>(
    "supportChat",
    addOrUpdateMessages
  );

  useTicketMessages({
    url: process.env.REACT_APP_DOMAIN + "/heruvym/getMessages",
    ticketId,
    messagesPerPage,
    messageApiPage,
    onSuccess: (messages) => {
      if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1)
        chatBoxRef.current.scrollTop = 1;
      addOrUpdateMessages(messages);
    },
    onError: (error: Error) => {
      const message = getMessageFromFetchError(error);
      if (message) enqueueSnackbar(message);
    },
    onFetchStateChange: setTicketMessageFetchState,
  });

  useSSESubscription<TicketMessage>({
    enabled: isActiveSSETab && Boolean(token) && Boolean(ticketId),
    url:
      process.env.REACT_APP_DOMAIN +
      `/heruvym/ticket?ticket=${ticketId}&Authorization=${token}`,
    onNewData: (ticketMessages) => {
      updateSSEValue(ticketMessages);
      addOrUpdateMessages(ticketMessages);
    },
    onDisconnect: useCallback(() => {
      clearMessageState();
      setIsPreventAutoscroll(false);
    }, []),
    marker: "ticket message",
  });

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

        const scrollBottom =
          chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight;
        const isPreventAutoscroll = scrollBottom > chatBox.clientHeight * 20;
        setIsPreventAutoscroll(isPreventAutoscroll);

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

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

  useEventListener("scroll", throttledScrollHandler, chatBoxRef);

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

      if (!isPreventAutoscroll) {
        setTimeout(() => {
          scrollToBottom();
        }, 50);
      }
    },
    [lastMessageId]
  );

  useEffect(() => {
    if (ticket) {
      shownMessage(ticket.top_message.id);
    }
  }, [ticket]);

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

    const [, sendTicketMessageError] = await sendTicketMessage(
      ticket.id,
      messageField
    );

    if (sendTicketMessageError) {
      return enqueueSnackbar(sendTicketMessageError);
    }

    setMessageField("");
  }

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

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

  const createdAt = ticket && new Date(ticket.created_at);
  const createdAtString =
    createdAt &&
    createdAt.toLocaleDateString(undefined, {
      year: "numeric",
      month: "2-digit",
      day: "2-digit",
    }) +
      " " +
      createdAt.toLocaleTimeString(undefined, {
        hour: "2-digit",
        minute: "2-digit",
      });

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

    if (ticketId) {
      if (file.size > MAX_FILE_SIZE) {
        return;
      }

      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 (
    <Box
      sx={{
        backgroundColor: upMd ? "white" : undefined,
        display: "flex",
        flexGrow: 1,
        maxHeight: upMd ? "443px" : undefined,
        borderRadius: "12px",
        p: upMd ? "20px" : undefined,
        gap: "40px",
        height: !upMd ? `calc(100% - ${isMobile ? 90 : 115}px)` : null,
        boxShadow: upMd ? cardShadow : undefined,
      }}
    >
      <Box
        sx={{
          display: "flex",
          alignItems: "start",
          flexDirection: "column",
          flexGrow: 1,
        }}
      >
        <Typography variant={upMd ? "h5" : "body2"} mb={"4px"}>
          {ticket?.title}
        </Typography>
        <Typography
          sx={{
            fontWeight: 400,
            fontSize: "14px",
            lineHeight: "17px",
            color: theme.palette.gray.main,
            mb: upMd ? "9px" : "20px",
          }}
        >
          Создан: {createdAtString}
        </Typography>
        <Box
          sx={{
            backgroundColor: "#ECECF3",
            border: `1px solid ${theme.palette.gray.main}`,
            borderRadius: "10px",
            overflow: "hidden",
            width: "100%",
            minHeight: "345px",
            display: "flex",
            flexGrow: 1,
            flexDirection: "column",
          }}
        >
          <Box
            sx={{
              position: "relative",
              width: "100%",
              flexGrow: 1,
              borderBottom: `1px solid ${theme.palette.gray.main}`,
              height: "200px",
            }}
          >
            {isPreventAutoscroll && (
              <Fab
                size="small"
                onClick={() => scrollToBottom("smooth")}
                sx={{
                  position: "absolute",
                  left: "10px",
                  bottom: "10px",
                }}
              >
                <ArrowDownwardIcon />
              </Fab>
            )}
            <Box
              ref={chatBoxRef}
              sx={{
                display: "flex",
                width: "100%",
                flexDirection: "column",
                gap: upMd ? "20px" : "16px",
                px: upMd ? "20px" : "5px",
                py: upMd ? "20px" : "13px",
                overflowY: "auto",
                height: "100%",
              }}
            >
              {ticket &&
                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 !== null &&
                    message.files.length > 0 &&
                    isFileImage()
                  ) {
                    return (
                      <ChatImage
                        unAuthenticated
                        key={message.id}
                        file={message.files[0]}
                        createdAt={message.created_at}
                        isSelf={ticket.user === message.user_id}
                      />
                    );
                  }
                  if (
                    message.files !== null &&
                    message.files.length > 0 &&
                    isFileVideo()
                  ) {
                    return (
                      <ChatVideo
                        unAuthenticated
                        key={message.id}
                        file={message.files[0]}
                        createdAt={message.created_at}
                        isSelf={ticket.user === message.user_id}
                      />
                    );
                  }
                  if (
                    message.files !== null &&
                    message.files.length > 0 &&
                    isFileDocument()
                  ) {
                    return (
                      <ChatDocument
                        unAuthenticated
                        key={message.id}
                        file={message.files[0]}
                        createdAt={message.created_at}
                        isSelf={ticket.user === message.user_id}
                      />
                    );
                  }

                  return (
                    <ChatMessage
                      unAuthenticated
                      key={message.id}
                      text={message.message}
                      createdAt={message.created_at}
                      isSelf={ticket.user === message.user_id}
                    />
                  );
                })}
            </Box>
          </Box>
          <FormControl>
            <InputBase
              value={messageField}
              fullWidth
              placeholder="Текст обращения"
              id="message"
              multiline
              sx={{
                width: "100%",
                p: 0,
              }}
              inputProps={{
                sx: {
                  fontWeight: 400,
                  fontSize: "16px",
                  lineHeight: "19px",
                  pt: upMd ? "13px" : "28px",
                  pb: upMd ? "13px" : "24px",
                  px: "19px",
                  maxHeight: "calc(19px * 5)",
                },
              }}
              onChange={(e) => setMessageField(e.target.value)}
              endAdornment={
                !upMd && (
                  <InputAdornment position="end">
                    <IconButton
                      sx={{ mr: "4px" }}
                      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
                      onClick={handleSendMessage}
                      sx={{
                        height: "45px",
                        width: "45px",
                        mr: "13px",
                        p: 0,
                      }}
                    >
                      <SendIcon />
                    </IconButton>
                  </InputAdornment>
                )
              }
            />
          </FormControl>
        </Box>
      </Box>
      {upMd && (
        <Box sx={{ alignSelf: "end" }}>
          <IconButton
            sx={{ mr: "4px" }}
            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"
          />
          <Button
            variant="pena-contained-dark"
            onClick={handleSendMessage}
            disabled={!messageField}
          >
            Отправить
          </Button>
        </Box>
      )}
    </Box>
  );
}

export default withErrorBoundary(SupportChat, {
  fallback: (
    <Typography mt="8px" textAlign="center">
      Не удалось отобразить чат
    </Typography>
  ),
  onError: handleComponentError,
});
