import {
  Box,
  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 CustomButton from "@components/CustomButton";
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,
  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";

export default function SupportChat() {
  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 token = useToken();
  const ticketId = useParams().ticketId;
  const ticket = tickets.find((ticket) => ticket.id === ticketId);
  const chatBoxRef = useRef<HTMLDivElement>(null);

  const fetchState = useTicketMessages({
    url: "https://admin.pena.digital/heruvym/getMessages",
    ticketId,
    messagesPerPage,
    messageApiPage,
    onNewMessages: useCallback((messages) => {
      if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1)
        chatBoxRef.current.scrollTop = 1;
      addOrUpdateMessages(messages);
    }, []),
    onError: useCallback((error: Error) => {
      const message = getMessageFromFetchError(error);
      if (message) enqueueSnackbar(message);
    }, []),
  });

  useSSESubscription<TicketMessage>({
    enabled: Boolean(token) && Boolean(ticketId),
    url: `https://admin.pena.digital/heruvym/ticket?ticket=${ticketId}&Authorization=${token}`,
    onNewData: addOrUpdateMessages,
    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);
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    },
    [lastMessageId]
  );

  useEffect(() => {
    if (ticket)
      makeRequest({
        url: "https://admin.pena.digital/heruvym/shown",
        method: "POST",
        useToken: true,
        body: { id: ticket.top_message.id },
      });
  }, [ticket]);

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

    makeRequest({
      url: "https://hub.pena.digital/heruvym/send",
      method: "POST",
      useToken: true,
      body: {
        ticket: ticket.id,
        message: messageField,
        lang: "ru",
        files: [],
      },
    })
      .then(() => {
        setMessageField("");
      })
      .catch((error) => {
        const errorMessage = getMessageFromFetchError(error);
        if (errorMessage) enqueueSnackbar(errorMessage);
      });
  }

  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",
      });

  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) => (
                  <ChatMessage
                    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
                      onClick={handleSendMessage}
                      sx={{
                        height: "45px",
                        width: "45px",
                        mr: "13px",
                        p: 0,
                      }}
                    >
                      <SendIcon />
                    </IconButton>
                  </InputAdornment>
                )
              }
            />
          </FormControl>
        </Box>
      </Box>
      {upMd && (
        <Box sx={{ alignSelf: "end" }}>
          <CustomButton
            onClick={handleSendMessage}
            disabled={!messageField}
            variant="contained"
            sx={{
              backgroundColor: theme.palette.purple.dark,
            }}
          >
            Отправить
          </CustomButton>
        </Box>
      )}
    </Box>
  );
}
