import { Box, IconButton, InputAdornment, TextField, Typography, useMediaQuery, useTheme } from "@mui/material";
import { addOrUpdateMessages, clearMessageState, incrementMessageApiPage, setIsPreventAutoscroll, setTicketMessagesFetchState, 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, useMemo, useRef, useState } from "react";
import { useParams } from "react-router-dom";
import { TicketMessage } from "@root/model/ticket";
import { sendTicketMessage } from "@root/api/tickets";
import { enqueueSnackbar } from "notistack";
import { useTicketStore } from "@root/stores/tickets";
import { getMessageFromFetchError, throttle, useEventListener, useSSESubscription, useTicketMessages, useToken } from "@frontend/kitui";


export default function Chat() {
    const token = useToken();
    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 isPreventAutoscroll = useMessageStore(state => state.isPreventAutoscroll);
    const fetchState = useMessageStore(state => state.ticketMessagesFetchState);
    const lastMessageId = useMessageStore(state => state.lastMessageId);

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

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

    useSSESubscription<TicketMessage>({
        enabled: Boolean(token) && Boolean(ticketId),
        url: process.env.REACT_APP_DOMAIN + `/heruvym/ticket?ticket=${ticketId}&Authorization=${token}`,
        onNewData: addOrUpdateMessages,
        onDisconnect: () => {
            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]);

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

    function handleAddAttachment() { }

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

    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",
        }}>
            <Typography>{ticket ? 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",
                }}
            >
                {ticket && messages.map(message =>
                    <Message key={message.id} message={message} isSelf={ticket.user !== message.user_id} />
                )}
            </Box>
            {ticket &&
                <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,
                        }
                    }}
                />
            }
        </Box>
    );
}
