import { Box, IconButton, InputAdornment, TextField, Typography, useMediaQuery, useTheme } from "@mui/material";
import { addOrUpdateMessages, clearMessageState, incrementMessageApiPage, setIsPreventAutoscroll, setMessageFetchState, useMessageStore } from "@root/stores/messages";
import Message from "./Message";
import SendIcon from "@mui/icons-material/Send";
import AttachFileIcon from "@mui/icons-material/AttachFile";
import { KeyboardEvent, useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import { GetMessagesRequest, TicketMessage } from "@root/model/ticket";
import { getTicketMessages, sendTicketMessage, subscribeToTicketMessages } from "@root/api/tickets";
import { enqueueSnackbar } from "notistack";
import { useTicketStore } from "@root/stores/tickets";
import { throttle } from "@root/utils/throttle";

import { authStore } from "@root/stores/auth";

export default function Chat() {
    const { token } = authStore();
    const theme = useTheme();
    const upMd = useMediaQuery(theme.breakpoints.up("md"));
    const tickets = useTicketStore(state => state.tickets);
    const messages = useMessageStore(state => state.messages);
    const [messageField, setMessageField] = useState<string>("");
    const ticketId = useParams().ticketId;
    const chatBoxRef = useRef<HTMLDivElement>(null);
    const messageApiPage = useMessageStore(state => state.apiPage);
    const messagesPerPage = useMessageStore(state => state.messagesPerPage);
    const messagesFetchStateRef = useRef(useMessageStore.getState().fetchState);
    const isPreventAutoscroll = useMessageStore(state => state.isPreventAutoscroll);
    const lastMessageId = useMessageStore(state => state.lastMessageId);

    const ticket = tickets.find(ticket => ticket.id === ticketId);

    useEffect(function scrollOnNewMessage() {
        scrollToBottom();
    }, [messages]);

  useEffect(
    function fetchTicketMessages() {
      if (!ticketId) return;

        const getTicketsBody: GetMessagesRequest = {
            amt: messagesPerPage,
            page: messageApiPage,
            ticket: ticketId,
        };
        const controller = new AbortController();

        setMessageFetchState("fetching");
        getTicketMessages({
            body: getTicketsBody,
            signal: controller.signal,
        }).then(result => {
            console.log("GetMessagesResponse", result);
            if (result?.length > 0) {
                addOrUpdateMessages(result);
                setMessageFetchState("idle");
            } else setMessageFetchState("all fetched");
        }).catch(error => {
            console.log("Error fetching messages", error);
            enqueueSnackbar(error.message);
        });

        return () => {
            controller.abort();
            clearMessageState();
        };
    }, [messageApiPage, messagesPerPage, ticketId]);

    useEffect(function subscribeToMessages() {
        if (!ticketId) return;

        if (!token) return;

      const unsubscribe = subscribeToTicketMessages({
        ticketId,
        accessToken: token,
        onMessage(event) {
          try {
            const newMessage = JSON.parse(event.data) as TicketMessage;
            console.log("SSE: parsed newMessage:", newMessage);
            addOrUpdateMessages([newMessage]);
          } catch (error) {
            console.log("SSE: couldn't parse:", event.data);
            console.log("Error parsing message SSE", error);
          }
        },
        onError(event) {
          console.log("SSE Error:", event);
        },
      });

        return () => {
            unsubscribe();
            clearMessageState();
            setIsPreventAutoscroll(false);
        };
    }, [ticketId]);

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

        const chatBox = chatBoxRef.current;
        const scrollHandler = () => {
            const scrollBottom = chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight;
            const isPreventAutoscroll = scrollBottom > chatBox.clientHeight;
            setIsPreventAutoscroll(isPreventAutoscroll);

            if (messagesFetchStateRef.current !== "idle") return;

            if (chatBox.scrollTop < chatBox.clientHeight) {
                if (chatBox.scrollTop < 1) chatBox.scrollTop = 1;
                incrementMessageApiPage();
            }
        };

        const throttledScrollHandler = throttle(scrollHandler, 200);
        chatBox.addEventListener("scroll", throttledScrollHandler);

        return () => {
            chatBox.removeEventListener("scroll", throttledScrollHandler);
        };
    }, []);

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

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

    useEffect(() => useMessageStore.subscribe(state => (messagesFetchStateRef.current = state.fetchState)), []);

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

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

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

        sendTicketMessage({
            body: {
                files: [],
                lang: "ru",
                message: messageField,
                ticket: ticket.id,
            }
        });
        setMessageField("");
    }

  function handleAddAttachment() {}

    function handleTextfieldKeyPress(e: KeyboardEvent) {
        if (e.key === "Enter" && !e.shiftKey) {
            e.preventDefault();
            handleSendMessage();
        }
    }

    const sortedMessages = messages.sort(sortMessagesByTime);

    return (
        <Box sx={{
            border: "1px solid",
            borderColor: theme.palette.grayDark.main,
            height: "600px",
            borderRadius: "3px",
            p: "8px",
            display: "flex",
            flex: upMd ? "2 0 0" : undefined,
            flexDirection: "column",
            justifyContent: "center",
            alignItems: "center",
            gap: "8px",
        }}>
            {ticket ?
                <>
                    <Typography>{ticket.title}</Typography>
                    <Box
                        ref={chatBoxRef}
                        sx={{
                            width: "100%",
                            backgroundColor: "#46474a",
                            flexGrow: 1,
                            display: "flex",
                            flexDirection: "column",
                            gap: "12px",
                            p: "8px",
                            overflow: "auto",
                            colorScheme: "dark",
                        }}
                    >
                        {sortedMessages.map(message =>
                            <Message key={message.id} message={message} isSelf={ticket.user !== message.user_id} />
                        )}
                    </Box>
                    <TextField
                        value={messageField}
                        onChange={e => setMessageField(e.target.value)}
                        onKeyPress={handleTextfieldKeyPress}
                        id="message-input"
                        placeholder="Написать сообщение"
                        fullWidth
                        multiline
                        maxRows={8}
                        InputProps={{
                            style: {
                                backgroundColor: theme.palette.content.main,
                                color: theme.palette.secondary.main,
                            },
                            endAdornment: (
                                <InputAdornment position="end">
                                    <IconButton
                                        onClick={handleSendMessage}
                                        sx={{
                                            height: "45px",
                                            width: "45px",
                                            p: 0,
                                        }}
                                    >
                                        <SendIcon sx={{ color: theme.palette.golden.main }} />
                                    </IconButton>
                                    <IconButton
                                        onClick={handleAddAttachment}
                                        sx={{
                                            height: "45px",
                                            width: "45px",
                                            p: 0,
                                        }}
                                    >
                                        <AttachFileIcon sx={{ color: theme.palette.golden.main }} />
                                    </IconButton>
                                </InputAdornment>
                            )
                        }}
                        InputLabelProps={{
                            style: {
                                color: theme.palette.secondary.main,
                            }
                        }}
                    />
                </>
                :
                <Typography>Выберите тикет</Typography>}
        </Box>
    );
}

function sortMessagesByTime(message1: TicketMessage, message2: TicketMessage) {
  const date1 = new Date(message1.created_at).getTime();
  const date2 = new Date(message2.created_at).getTime();
  return date1 - date2;
}
