import { Box, Fab, FormControl, IconButton, InputAdornment, InputBase, Typography, useMediaQuery, useTheme, } from "@mui/material";
import ArrowDownwardIcon from "@mui/icons-material/ArrowDownward";
import { useEffect, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import CustomButton from "@components/CustomButton";
import SendIcon from "@components/icons/SendIcon";
import { throttle } from "@utils/decorators";
import { enqueueSnackbar } from "notistack";
import { useTicketStore } from "@root/stores/tickets";
import { addOrUpdateMessages, clearMessageState, incrementMessageApiPage, setIsPreventAutoscroll, setMessageFetchState, useMessageStore } from "@root/stores/messages";
import { getTicketMessages, sendTicketMessage, subscribeToTicketMessages } from "@root/api/tickets";
import { GetMessagesRequest, TicketMessage } from "@root/model/ticket";
import { authStore } from "@root/stores/makeRequest";
import ChatMessage from "@root/components/ChatMessage";


export default function SupportChat() {
    const theme = useTheme();
    const upMd = useMediaQuery(theme.breakpoints.up("md"));
    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 messagesFetchStateRef = useRef(useMessageStore.getState().fetchState);
    const token = authStore(state => state.token);
    const ticketId = useParams().ticketId;
    const ticket = tickets.find(ticket => ticket.id === ticketId);
    const chatBoxRef = useRef<HTMLDivElement>();

    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) {
                if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1) chatBoxRef.current.scrollTop = 1;
                addOrUpdateMessages(result);
                setMessageFetchState("idle");
            } else setMessageFetchState("all fetched");
        }).catch(error => {
            console.log("Error fetching messages", error);
            enqueueSnackbar(error.message);
        });

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

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

        const unsubscribe = subscribeToTicketMessages({
            ticketId: 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();
        };
    }, [ticketId, token]);

    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) {
                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 handleSendMessage() {
        if (!ticket || !messageField) return;

        sendTicketMessage({
            ticket: ticket.id,
            message: messageField,
            lang: "ru",
            files: [],
        });
        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",
    });

    return (
        <Box sx={{
            backgroundColor: upMd ? "white" : undefined,
            display: "flex",
            flexGrow: 1,
            maxHeight: upMd ? "443px" : undefined,
            borderRadius: "12px",
            p: upMd ? "20px" : undefined,
            gap: "40px",
            boxShadow: upMd
                ? `0px 100px 309px rgba(210, 208, 225, 0.24), 
                        0px 41.7776px 129.093px rgba(210, 208, 225, 0.172525),
                        0px 22.3363px 69.0192px rgba(210, 208, 225, 0.143066), 
                        0px 12.5216px 38.6916px rgba(210, 208, 225, 0.12), 
                        0px 6.6501px 20.5488px rgba(210, 208, 225, 0.0969343), 
                        0px 2.76726px 8.55082px rgba(210, 208, 225, 0.0674749)`
                : 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.grey2.main,
                        mb: upMd ? "9px" : "20px",
                    }}
                >
                    Создан: {createdAtString}
                </Typography>
                <Box
                    sx={{
                        backgroundColor: "#ECECF3",
                        border: `1px solid ${theme.palette.grey2.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.grey2.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.brightPurple.main,
                        }}
                    >
                        Отправить
                    </CustomButton>
                </Box>
            )}
        </Box>
    );
}