import { memo, useCallback, useMemo, useState } from 'react';
import { useParams } from 'react-router';

import { IconMoodSmile } from '@material-hu/icons/tabler';
import Stack from '@material-hu/mui/Stack';
import Typography from '@material-hu/mui/Typography';

import IconSelector, {
  type IconSelectorProps,
} from '@material-hu/components/design-system/IconSelector';

import { useAuth } from 'src/contexts/JWTContext';
import useFeatureFlag from 'src/hooks/useFeatureFlag';
import {
  BUBBLE_CLASS,
  MAX_EMOJIS_LIMIT,
} from 'src/pages/dashboard/Conversations/constants';
import {
  type BloackMessageReplied,
  type ConversationMessage,
  type Member,
} from 'src/pages/dashboard/Conversations/types';
import { useReactionsWithUsers } from 'src/pages/dashboard/Conversations/hooks/useReactionsWithUsers';
import { compareIds } from 'src/pages/dashboard/Conversations/utils';
import { FeatureFlags } from 'src/types/featureFlags';

import {
  useGetPinnedMessages,
  useReactionsMutations,
} from '../../../hooks/useConversationsQueries';
import MessageSetting from '../../MessageSetting';

import MessageAttachments from './MessageAttachments';
import MessageBubble from './MessageBubble';
import MessageContainer from './MessageContainer';
import MessageFooter from './MessageFooter';
import MessageForwardHeader from './MessageForwardHeader';
import MessageReactions from './MessageReactions';
import MessageReplied from './MessageReplied';
import MessageRow from './MessageRow';
import MessageText from './MessageText';

type OnEmojiSelectPayload = Parameters<
  NonNullable<IconSelectorProps['onEmojiSelect']>
>[0];

type BubbleContentProps = {
  message: ConversationMessage;
  nextMessage?: ConversationMessage;
  members: Member[];
  isLoggedUser: boolean;
  isGroupConversation: boolean;
  showUserPic: boolean;
  isSystemMessage: boolean;
  isKnownBlock: boolean;
  isMessageReplied?: boolean;
  isMessageForwarded?: boolean;
  isSelfConversation: boolean;
};

const BubbleContent = ({
  message,
  members,
  isLoggedUser,
  isGroupConversation,
  showUserPic,
  isSystemMessage,
  isKnownBlock,
  isMessageReplied = false,
  isMessageForwarded = false,
  isSelfConversation,
  nextMessage,
}: BubbleContentProps) => {
  const { id } = useParams();

  const [showEmojiPicker, setShowEmojiPicker] = useState(false);
  const [showHoverEmojiPicker, setShowHoverEmojiPicker] = useState(false);
  const [menuAnchorEl, setMenuAnchorEl] = useState<HTMLElement | null>(null);
  const [isContentClicked, setIsContentClicked] = useState(false);
  const [hasGifError, setHasGifError] = useState(false);
  const { user } = useAuth();
  const { mutate: mutateReaction } = useReactionsMutations();
  const handleReactionSelect = useCallback(
    ({ emoji }: OnEmojiSelectPayload) => {
      if (!user) return;
      const hasReacted = message.reactions?.some(
        r => r.name === emoji && r.users.includes(user.id.toString()),
      );
      mutateReaction({
        channel: message.channel,
        ts: message.hu_data.message_ts,
        name: emoji,
        hasReacted,
        userId: user.id.toString(),
      });
    },
    [
      user,
      message.reactions,
      message.channel,
      message.hu_data.message_ts,
      mutateReaction,
    ],
  );

  const handleReactClick = useCallback((anchorEl: HTMLElement | null) => {
    setMenuAnchorEl(anchorEl);
    setShowHoverEmojiPicker(true);
  }, []);

  const handleHoverPickerOpenChange = useCallback((open: boolean) => {
    setShowHoverEmojiPicker(open);
    if (!open) setMenuAnchorEl(null);
  }, []);
  const reactionsWithUsers = useReactionsWithUsers(message.reactions, id);
  const enabledPinMessage = useFeatureFlag(FeatureFlags.CHATS_V2_PIN_MESSAGE);
  const { data: pinnedMessages = [] } = useGetPinnedMessages({
    channelId: message.channel,
    enabled: enabledPinMessage,
  });
  const isPinnedMessage = useMemo(() => {
    if (!enabledPinMessage) return false;
    const messageTs = message.hu_data?.message_ts;
    return pinnedMessages.some(pm => pm.hu_data?.message_ts === messageTs);
  }, [enabledPinMessage, pinnedMessages, message.hu_data?.message_ts]);
  const { attachments, username } = message;
  const allowAddEmoji = reactionsWithUsers?.length < MAX_EMOJIS_LIMIT;
  const handleMouseUp = (event: React.MouseEvent<HTMLDivElement>) => {
    if (
      event.target instanceof HTMLElement &&
      event.target.closest(`.${BUBBLE_CLASS}`)
    ) {
      setIsContentClicked(false);
    }
  };

  const handleMouseEnter = (event: React.MouseEvent<HTMLDivElement>) => {
    const isMouseDown = event.buttons === 1;
    setIsContentClicked(isMouseDown);
  };

  const handleMouseMove = (event: React.MouseEvent<HTMLDivElement>) => {
    const isMouseDown = event.buttons === 1;
    if (!isMouseDown) return;

    const selection = window.getSelection();
    const hasSelection = selection && selection.toString().length > 0;
    setIsContentClicked(hasSelection || false);
  };

  const showSmile = !message.hidden;
  return (
    <MessageContainer isLoggedUser={isLoggedUser}>
      <MessageRow isLoggedUser={isLoggedUser}>
        <MessageBubble
          message={message}
          onMouseUp={handleMouseUp}
          onMouseEnter={handleMouseEnter}
          onMouseMove={handleMouseMove}
          isLoggedUser={isLoggedUser}
        >
          <MessageSetting
            message={message}
            isLoggedUser={isLoggedUser}
            onReactClick={handleReactClick}
            reactions={reactionsWithUsers}
            members={members}
            isContentClicked={isContentClicked}
            isMessageForwarded={isMessageForwarded || false}
            isGroupConversation={isGroupConversation}
            isPinnedMessage={isPinnedMessage}
            pinnedMessagesCount={pinnedMessages.length}
          />

          {isGroupConversation && !isLoggedUser && showUserPic && (
            <Typography
              variant="globalS"
              fontWeight="fontWeightSemiBold"
            >
              {username}
            </Typography>
          )}
          {isMessageReplied && !isMessageForwarded && (
            <MessageReplied
              isLoggedUser={isLoggedUser}
              messageReply={message?.blocks?.[0] as BloackMessageReplied}
              messageId={message.hu_data.message_ts}
            />
          )}
          {isMessageForwarded && <MessageForwardHeader />}
          {!!attachments?.length && (
            <MessageAttachments
              message={message}
              isLoggedUserMessage={compareIds(message.user, user?.id)}
              isMessageReplied={isMessageReplied || false}
              isMessageForwarded={isMessageForwarded || false}
              nextMessage={nextMessage}
              onGifError={() => setHasGifError(true)}
              isLoggedUser={isLoggedUser}
            />
          )}
          <MessageText
            isKnownBlock={isKnownBlock}
            isSystemMessage={isSystemMessage}
            text={message.text || ''}
            isDeleted={message?.hidden || false}
            isLoggedUser={isLoggedUser}
            highlightedSpans={message.hu_data.highlighted_spans}
            messageId={message.hu_data.message_ts}
          />

          <MessageFooter
            message={message}
            isDeleted={message?.hidden || false}
            isSelfConversation={isSelfConversation}
            isPinnedMessage={isPinnedMessage}
            isVisible={
              (!isSystemMessage || isMessageReplied || isMessageForwarded) &&
              !hasGifError
            }
          />
        </MessageBubble>

        {showSmile && allowAddEmoji && (
          <Stack
            className="hover-smile"
            sx={{
              flex: 1,
              justifyContent: 'center',
              opacity: 0,
              visibility: 'hidden',
            }}
          >
            <IconSelector
              mode="emoji"
              icon={<IconMoodSmile size={24} />}
              onEmojiSelect={handleReactionSelect}
              slotProps={{ iconButton: { size: 'small', variant: 'tertiary' } }}
              open={showHoverEmojiPicker}
              onOpenChange={handleHoverPickerOpenChange}
              closeOnScroll
              anchorEl={menuAnchorEl ?? undefined}
            />
          </Stack>
        )}
      </MessageRow>

      {showSmile && (
        <MessageReactions
          reactions={reactionsWithUsers}
          message={message}
          showEmojiPicker={showEmojiPicker}
          setShowEmojiPicker={setShowEmojiPicker}
        />
      )}
    </MessageContainer>
  );
};

export default memo(BubbleContent);
