import { FC, useEffect, useState, useRef } from 'react';

import Box from '@material-hu/mui/Box';
import Divider from '@material-hu/mui/Divider';
import ListItem from '@material-hu/mui/ListItem';
import ListItemAvatar from '@material-hu/mui/ListItemAvatar';
import ListItemText from '@material-hu/mui/ListItemText';
import Typography from '@material-hu/mui/Typography';

import { EVENTS_SOCKETS } from 'src/constants/sockets';
import { useAuth } from 'src/contexts/JWTContext';
import { useSocket } from 'src/contexts/SocketContext';
import useProfile from 'src/hooks/queryHooks/profile';
import { ChatListItem } from 'src/types/chats';
import { showMessageUserName } from 'src/utils/chats';
import { formatRelativeDate } from 'src/utils/date';

import Badge from 'src/components/Badge';
import ChatAvatar from 'src/components/dashboard/chat/ChatAvatar';
import ChatName from 'src/components/dashboard/chat/ChatName';
import { useTranslation } from 'src/components/dashboard/chat/i18n';
import ReduceMessage from 'src/components/dashboard/chat/ReduceMessage';
import ThreadItemContextMenu from 'src/components/dashboard/chat/ThreadList/ThreadItemContextMenu';
import ThreadItemIconMenu from 'src/components/dashboard/chat/ThreadList/ThreadItemIconMenu';

export type ThreadItemProps = {
  active?: boolean;
  onClick: (event) => void;
  thread: ChatListItem;
  isForm?: boolean;
};

const ThreadItem: FC<ThreadItemProps> = props => {
  const { active, thread, onClick, isForm = false } = props;

  const [typing, setTyping] = useState(false);
  const [hover, setHover] = useState(false);

  const itemRef = useRef<HTMLDivElement>(null);
  const { t } = useTranslation();
  const socket = useSocket();
  const { user } = useAuth();

  const {
    chat: { lastMessage, unreadMessages, markedAsUnread, otherUser },
    chatType,
  } = thread;

  const createdAt = lastMessage?.createdAt || '';

  const { data: userData } = useProfile(
    lastMessage?.userId,
    showMessageUserName(lastMessage?.userId, chatType),
  );

  let typingCounter = 0;
  let typingCounterAux = 0;

  useEffect(() => {
    const setUserTyping = data => {
      if (data.typingUser.id !== user.id && thread.chat.id === data.chatId) {
        typingCounter += 1;
        setTyping(true);
      }
    };

    const typingInterval = setInterval(() => {
      if (typingCounter === typingCounterAux) {
        typingCounter = 0;
        typingCounterAux = 0;
        setTyping(false);
      }
      typingCounterAux = typingCounter;
    }, 2000);

    socket.listenEvent(EVENTS_SOCKETS.TYPING, setUserTyping);

    return () => {
      socket.closeEvent(EVENTS_SOCKETS.TYPING, setUserTyping);
      clearInterval(typingInterval);
    };
  }, [socket, user.id, thread.chat.id]);

  const getMessageWithUser = () => {
    const messageUserId = lastMessage?.userId;
    const messageUserName = userData?.data?.firstName;
    const showName = showMessageUserName(messageUserId, chatType);
    const message = (
      <Box
        component="span"
        sx={{
          display: 'flex',
          flexDirection: 'row',
        }}
      >
        <ReduceMessage
          message={lastMessage}
          isTyping={typing}
          isGroupMessage={!!showName}
        />
      </Box>
    );

    if (!showName || typing) {
      return message;
    }

    if (messageUserId === user.id) {
      return (
        <Box
          component="span"
          sx={{
            display: 'flex',
            flexDirection: 'row',
          }}
        >
          <Box
            component="span"
            sx={{ mr: 0.5 }}
          >
            {t('MY_MESSAGE')}
          </Box>
          {message}
        </Box>
      );
    }
    if (messageUserName) {
      return (
        <Box
          component="span"
          sx={{
            display: 'flex',
            flexDirection: 'row',
          }}
        >
          <Box
            component="span"
            sx={{ mr: 0.5 }}
          >
            {t('USER_MESSAGE', { user: messageUserName })}
          </Box>
          {message}
        </Box>
      );
    }
  };

  const handleOnMouseOver = () => setHover(true);
  const handleOnMouseLeave = () => setHover(false);
  const handleClose = () => setHover(false);

  if (hover && itemRef?.current?.matches(':hover') === false) {
    setHover(false);
  }

  const handleOnClick = event => onClick(event);

  const avatarSize = isForm ? 36 : 42;

  return (
    <ThreadItemContextMenu thread={thread}>
      <ListItem
        ref={itemRef}
        button
        onClick={handleOnClick}
        onMouseOver={handleOnMouseOver}
        onMouseLeave={handleOnMouseLeave}
        sx={{
          backgroundColor: active && 'action.selected',
          boxShadow: theme =>
            active && `inset 4px 0px 0px ${theme.palette.primary.main}`,
          px: 2,
          display: 'flex',
          justifyContent: 'center',
        }}
      >
        <ListItemAvatar
          sx={{
            display: 'flex',
            justifyContent: {
              sm: 'flex-center',
              xs: 'center',
              minWidth: isForm ? '56px' : 'auto',
            },
          }}
        >
          <ChatAvatar
            thread={thread}
            withLink={false}
            withUserDeleted
            sx={{
              height: avatarSize,
              width: avatarSize,
              mr: isForm ? 0 : 2,
            }}
          />
        </ListItemAvatar>
        <>
          <ListItemText
            sx={{ paddingRight: '5px' }}
            primary={
              <ChatName
                thread={thread}
                withLink={false}
                otherUser={otherUser}
                withUserDeleted
              />
            }
            primaryTypographyProps={{
              color: otherUser?.deleted ? 'grey' : 'textPrimary',
              noWrap: true,
              variant: 'subtitle2',
            }}
            secondary={getMessageWithUser()}
            secondaryTypographyProps={{
              color: !typing ? 'textSecondary' : 'green',
              noWrap: true,
              variant: 'body2',
            }}
          />
          <Box
            sx={{
              display: 'flex',
              flexDirection: 'column',
              alignSelf: 'flex-start',
              my: '6px',
              pr: 0,
            }}
          >
            <Typography
              color="textSecondary"
              variant="body2"
            >
              {formatRelativeDate(new Date(createdAt))}
            </Typography>
            <Box
              sx={{
                display: 'flex',
                flexDirection: 'row',
                justifyContent: 'flex-end',
              }}
            >
              {(unreadMessages > 0 || markedAsUnread) && (
                <Typography
                  color="textPrimary"
                  variant="subtitle2"
                  textAlign="end"
                >
                  <Badge
                    count={unreadMessages}
                    isUnread={markedAsUnread}
                  />
                </Typography>
              )}
              {hover && (
                <ThreadItemIconMenu
                  onClose={handleClose}
                  thread={thread}
                />
              )}
            </Box>
          </Box>
        </>
      </ListItem>
      <Divider sx={{ width: '100%', marginLeft: '56px' }} />
    </ThreadItemContextMenu>
  );
};

export default ThreadItem;
