import { Box, FormControl, IconButton, InputAdornment, InputBase, SxProps, Theme, Typography, useMediaQuery, useTheme } from "@mui/material";
import { createTicket, getUnauthTicketMessages, sendTicketMessage, subscribeToUnauthTicketMessages } from "@root/api/tickets";
import { GetMessagesRequest, TicketMessage } from "@root/model/ticket";
import { addOrUpdateUnauthMessages, setUnauthTicketFetchState, useUnauthTicketStore, incrementUnauthMessageApiPage, setUnauthIsPreventAutoscroll, setUnauthSessionData } from "@root/stores/unauthTicket";
import { enqueueSnackbar } from "notistack";
import { useEffect, useRef, useState } from "react";
import ChatMessage from "../ChatMessage";
import SendIcon from "../icons/SendIcon";
import UserCircleIcon from "./UserCircleIcon";
import { throttle } from "@root/utils/decorators";


interface Props {
    sx?: SxProps<Theme>;
}

export default function Chat({ sx }: Props) {
    const theme = useTheme();
    const upMd = useMediaQuery(theme.breakpoints.up("md"));
    const [messageField, setMessageField] = useState<string>("");
    const sessionData = useUnauthTicketStore(state => state.sessionData);
    const messages = useUnauthTicketStore(state => state.messages);
    const messageApiPage = useUnauthTicketStore(state => state.apiPage);
    const messagesPerPage = useUnauthTicketStore(state => state.messagesPerPage);
    const messagesFetchStateRef = useRef(useUnauthTicketStore.getState().fetchState);
    const isPreventAutoscroll = useUnauthTicketStore(state => state.isPreventAutoscroll);
    const lastMessageId = useUnauthTicketStore(state => state.lastMessageId);
    const chatBoxRef = useRef<HTMLDivElement>();

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

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

        setUnauthTicketFetchState("fetching");
        getUnauthTicketMessages({
            body: getTicketsBody,
            signal: controller.signal,
        }).then(result => {
            console.log("GetMessagesResponse", result);
            if (result?.length > 0) {
                addOrUpdateUnauthMessages(result);
                setUnauthTicketFetchState("idle");
            } else setUnauthTicketFetchState("all fetched");
        }).catch(error => {
            console.log("Error fetching messages", error);
            if (error.code !== "ERR_CANCELED") enqueueSnackbar(error.message);
        });

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

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

        const unsubscribe = subscribeToUnauthTicketMessages({
            sessionId: sessionData.sessionId,
            ticketId: sessionData.ticketId,
            onMessage(event) {
                try {
                    const newMessage = JSON.parse(event.data) as TicketMessage;
                    if (!newMessage.id) throw new Error("Bad SSE response");
                    console.log("SSE: parsed newMessage:", newMessage);
                    addOrUpdateUnauthMessages([newMessage]);
                } catch (error) {
                    console.log("SSE: couldn't parse:", event.data);
                    console.log("Error parsing SSE message", error);
                }
            },
            onError(event) {
                console.log("SSE Error:", event);
            },
        });

        return () => {
            unsubscribe();
            // clearUnauthTicketState();
            setUnauthIsPreventAutoscroll(false);
        };
    }, [sessionData]);

    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;
            setUnauthIsPreventAutoscroll(isPreventAutoscroll);

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

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

        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(() => useUnauthTicketStore.subscribe(state => (messagesFetchStateRef.current = state.fetchState)), []);

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

        if (!sessionData) {
            const response = await createTicket({
                Title: "Unauth title",
                Message: messageField,
            }, false);

            setUnauthSessionData({
                ticketId: response.Ticket,
                sessionId: response.sess,
            });
        } else {
            sendTicketMessage({
                ticket: sessionData.ticketId,
                message: messageField,
                lang: "ru",
                files: [],
            }, true).catch(error => {
                console.log("Coudn't send message", error);
                enqueueSnackbar(error.message);
            });
        }

        setMessageField("");
    }

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

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

    const handleTextfieldKeyPress: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement> = (e) => {
        if (e.key === "Enter" && !e.shiftKey) {
            e.preventDefault();
            handleSendMessage();
        }
    };

    return (
        <Box sx={{
            display: "flex",
            flexDirection: "column",
            height: "clamp(250px, 100dvh - 90px, 600px)",
            backgroundColor: "#944FEE",
            borderRadius: "8px",
            ...sx,
        }}>
            <Box sx={{
                display: "flex",
                gap: "9px",
                pl: "22px",
                pt: "12px",
                pb: "20px",
                filter: "drop-shadow(0px 3px 12px rgba(37, 39, 52, 0.3))",
            }}>
                <UserCircleIcon />
                <Box sx={{
                    mt: "5px",
                    display: "flex",
                    flexDirection: "column",
                    gap: "3px",
                }}>
                    <Typography>Мария</Typography>
                    <Typography sx={{
                        fontSize: "16px",
                        lineHeight: "19px",
                    }}>онлайн-консультант</Typography>
                </Box>
            </Box>
            <Box sx={{
                flexGrow: 1,
                backgroundColor: "white",
                borderRadius: "8px",
                display: "flex",
                flexDirection: "column",
            }}>
                <Box
                    ref={chatBoxRef}
                    sx={{
                        display: "flex",
                        width: "100%",
                        flexBasis: 0,
                        flexDirection: "column",
                        gap: upMd ? "20px" : "16px",
                        px: upMd ? "20px" : "5px",
                        py: upMd ? "20px" : "13px",
                        overflowY: "auto",
                        flexGrow: 1,
                    }}
                >
                    {sessionData && messages.map((message) => (
                        <ChatMessage
                            unAuthenticated
                            key={message.id}
                            text={message.message}
                            createdAt={message.created_at}
                            isSelf={sessionData.sessionId === message.user_id}
                        />
                    ))}
                </Box>
                <FormControl fullWidth sx={{ borderTop: "1px solid black" }}>
                    <InputBase
                        value={messageField}
                        fullWidth
                        placeholder="Введите сообщение..."
                        id="message"
                        multiline
                        onKeyDown={handleTextfieldKeyPress}
                        sx={{
                            width: "100%",
                            p: 0,
                        }}
                        inputProps={{
                            sx: {
                                fontWeight: 400,
                                fontSize: "16px",
                                lineHeight: "19px",
                                pt: upMd ? "30px" : "28px",
                                pb: upMd ? "30px" : "24px",
                                px: "19px",
                                maxHeight: "calc(19px * 5)",
                                color: "black",
                            },
                        }}
                        onChange={(e) => setMessageField(e.target.value)}
                        endAdornment={
                            <InputAdornment position="end">
                                <IconButton
                                    onClick={handleSendMessage}
                                    sx={{
                                        height: "53px",
                                        width: "53px",
                                        mr: "13px",
                                        p: 0,
                                    }}
                                >
                                    <SendIcon style={{
                                        width: "100%",
                                        height: "100%",
                                    }} />
                                </IconButton>
                            </InputAdornment>
                        }
                    />
                </FormControl>
            </Box>
        </Box>
    );
}