import {
	Box,
	FormControl,
	IconButton,
	InputAdornment,
	InputBase,
	SxProps,
	Theme,
	Typography,
	useMediaQuery,
	useTheme,
} from "@mui/material"
import { TicketMessage } from "@frontend/kitui"
import {
	addOrUpdateUnauthMessages,
	useUnauthTicketStore,
	incrementUnauthMessageApiPage,
	setUnauthIsPreventAutoscroll,
	setUnauthSessionData,
	setIsMessageSending,
	setUnauthTicketMessageFetchState,
} from "@root/stores/unauthTicket"
import { enqueueSnackbar } from "notistack"
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import ChatMessage from "../ChatMessage"
import SendIcon from "../icons/SendIcon"
import UserCircleIcon from "./UserCircleIcon"
import { throttle } from "@frontend/kitui"
import {
	useTicketMessages,
	getMessageFromFetchError,
	useSSESubscription,
	useEventListener,
	createTicket,
} from "@frontend/kitui"
import { sendTicketMessage } from "@root/api/ticket"

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 isMessageSending = useUnauthTicketStore(
		(state) => state.isMessageSending
	)
	const isPreventAutoscroll = useUnauthTicketStore(
		(state) => state.isPreventAutoscroll
	)
	const lastMessageId = useUnauthTicketStore((state) => state.lastMessageId)
	const fetchState = useUnauthTicketStore(
		(state) => state.unauthTicketMessageFetchState
	)
	const chatBoxRef = useRef<HTMLDivElement>(null)

	useTicketMessages({
		url: process.env.REACT_APP_DOMAIN + "/heruvym/getMessages",
		isUnauth: true,
		ticketId: sessionData?.ticketId,
		messagesPerPage,
		messageApiPage,
		onSuccess: useCallback((messages) => {
			if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1)
				chatBoxRef.current.scrollTop = 1
			addOrUpdateUnauthMessages(messages)
		}, []),
		onError: useCallback((error: Error) => {
			const message = getMessageFromFetchError(error)
			if (message) enqueueSnackbar(message)
		}, []),
		onFetchStateChange: setUnauthTicketMessageFetchState,
	})

	useSSESubscription<TicketMessage>({
		enabled: Boolean(sessionData),
		url: process.env.REACT_APP_DOMAIN + `/heruvym/ticket?ticket=${sessionData?.ticketId}&s=${sessionData?.sessionId}`,
		onNewData: addOrUpdateUnauthMessages,
		onDisconnect: useCallback(() => {
			setUnauthIsPreventAutoscroll(false)
		}, []),
		marker: "ticket",
	})

	const throttledScrollHandler = useMemo(
		() =>
			throttle(() => {
				const chatBox = chatBoxRef.current
				if (!chatBox) return

				const scrollBottom =
          chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight
				const isPreventAutoscroll = scrollBottom > chatBox.clientHeight
				setUnauthIsPreventAutoscroll(isPreventAutoscroll)

				if (fetchState !== "idle") return

				if (chatBox.scrollTop < chatBox.clientHeight) {
					incrementUnauthMessageApiPage()
				}
			}, 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]
	)

	async function handleSendMessage() {
		if (!messageField || isMessageSending) return

		if (!sessionData) {
			setIsMessageSending(true)
			createTicket({
				url: process.env.REACT_APP_DOMAIN + "/heruvym/create",
				body: {
					Title: "Unauth title",
					Message: messageField,
				},
				useToken: false,
			})
				.then((response) => {
					setUnauthSessionData({
						ticketId: response.Ticket,
						sessionId: response.sess,
					})
				})
				.catch((error) => {
					const errorMessage = getMessageFromFetchError(error)
					if (errorMessage) enqueueSnackbar(errorMessage)
				})
				.finally(() => {
					setMessageField("")
					setIsMessageSending(false)
				})
		} else {
			setIsMessageSending(true)

			const [_, sendTicketMessageError] = await sendTicketMessage(
				sessionData.ticketId,
				messageField
			)

			if (sendTicketMessageError) {
				enqueueSnackbar(sendTicketMessageError)
			}

			setMessageField("")
			setIsMessageSending(false)
		}
	}

	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, calc(100vh - 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
									disabled={isMessageSending}
									onClick={handleSendMessage}
									sx={{
										height: "53px",
										width: "53px",
										mr: "13px",
										p: 0,
										opacity: isMessageSending ? 0.3 : 1,
									}}
								>
									<SendIcon
										style={{
											width: "100%",
											height: "100%",
										}}
									/>
								</IconButton>
							</InputAdornment>
						}
					/>
				</FormControl>
			</Box>
		</Box>
	)
}
