import React, {memo, useCallback, useMemo, useRef} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {IconAt, IconBellOff, IconPin} from '@tabler/icons-react-native';
import {useNavigation} from '@react-navigation/native';
import {Badge, ListRow, Typography} from '@components';
import {
  closeAllSwipeables,
  RNSwipeable,
  SwipeableRef,
} from '@components/RNSwipeable';
import {ScreenOpenPerfTracker} from '@config/sentry';
import {useEvent} from '@hooks/useEvent';
import {useHumanizedDate} from '@modules/chats/hooks';
import {ChatNotificationType, Conversation} from '@modules/chats/interfaces';
import {
  CHAT_LIST_AVATAR_SIZE,
  getChatAvatar,
  getChatImage,
} from '@modules/chats/utils';
import {useUnreadCount} from '@modules/chats/store';
import {showSnackbar} from '@redux/dispatchers';
import {persistedUserId} from '@services/localStorage';
import {SPACING, useTheme} from '@shared/theme';
import {Screens} from '@shared/constants';
import {sentryLogs} from '@shared/utils';

import {LastMessage} from '../LastMessage';
import {styles} from './styles';
import {LEFT_ACTION_WIDTH, LeftActions} from './components/LeftActions';
import {RightActions} from './components/RightActions';

interface Props {
  chat: Conversation;
  onPress?: () => void;
  onMorePress?: (target: Conversation) => void;
  onPinPress?: (target: Conversation) => void;
  onMarkAsUnreadPress?: (target: Conversation, unreadCount: number) => void;
}

function ChatListItemComponent({
  chat,
  onPress,
  onMorePress,
  onPinPress,
  onMarkAsUnreadPress,
}: Props) {
  const {t} = useTranslation();
  const userId = persistedUserId!;
  const {id, latest, is_channel, mentioned, properties} = chat;
  const {theme} = useTheme();
  const navigation = useNavigation();
  const avatar = useMemo(() => getChatAvatar(chat, userId), [chat, userId]);
  const avatarUrl = getChatImage.avatar(avatar.url, {
    avatarSize: CHAT_LIST_AVATAR_SIZE,
  });
  const date = useHumanizedDate(chat.latest?.ts);
  const unread_count = useUnreadCount(id);
  const showBadge = unread_count > 0 || !!chat.properties?.marked_unread_at;
  const isMuted =
    properties?.notification_status?.notification_type !==
    ChatNotificationType.All;
  const isPinned = !!properties?.pinned_at;
  const isMarkedUnread =
    !!chat.properties?.marked_unread_at || unread_count > 0;
  const showMentioned = mentioned && showBadge;

  const isSwipeGestureRef = useRef(false);
  const swipeableRef = useRef<SwipeableRef | null>(null);

  const onChatPress = useEvent(() => {
    if (isSwipeGestureRef.current) {
      isSwipeGestureRef.current = false;
      return;
    }

    onPress?.();

    if (!chat.id) {
      sentryLogs.error({
        message: 'Conversation id not defined',
        module: 'CHATS',
        component: 'ChatListItem',
      });
      showSnackbar({
        title: t('errors.api.500', {info: ''}),
        variant: 'error',
      });
      return;
    }

    ScreenOpenPerfTracker.start(Screens.CHAT_MESSAGES);
    navigation.navigate(Screens.CHAT_MESSAGES, {
      id: chat.id,
    });
    closeAllSwipeables();
  });

  const onRightActionsPress = useEvent(() => {
    swipeableRef.current?.close();
    onMorePress?.(chat);
  });

  const onPinPressInternal = useEvent(() => {
    swipeableRef.current?.close();
    onPinPress?.(chat);
  });

  const onMarkAsUnreadPressInternal = useEvent(() => {
    swipeableRef.current?.close();
    onMarkAsUnreadPress?.(chat, unread_count);
  });

  const onSwipeableBegan = useCallback(() => {
    isSwipeGestureRef.current = true;
  }, []);

  const onSwipeableFinish = useCallback(() => {
    isSwipeGestureRef.current = false;
  }, []);

  return (
    <RNSwipeable
      ref={swipeableRef}
      onSwipeableBegan={onSwipeableBegan}
      onSwipeableFinish={onSwipeableFinish}
      maxRightOffset={LEFT_ACTION_WIDTH}
      style={styles.swipeable}>
      <LeftActions
        isPinned={isPinned}
        onPinPress={onPinPressInternal}
        onMarkAsUnreadPress={onMarkAsUnreadPressInternal}
        isMarkedUnread={isMarkedUnread}
      />
      <ListRow
        backgroundColor={'transparent'}
        pressedColor={theme.background.layout.default}
        onPress={onChatPress}
        style={styles.listItem}>
        <ListRow.Avatar
          {...avatar}
          url={avatarUrl}
          style={styles.avatar}
          // forces the image component to reset and load the new image immediately
          // avoids showing image from a wrong conversation when recycling
          recyclingKey={id}
        />
        <View style={styles.wrapper}>
          <View style={styles.descriptionContainer}>
            <ListRow.Title
              title={avatar.title}
              titleMaxFontSizeMultiplier={100}
              flex={false}
            />
            <LastMessage message={latest} isChannel={!!is_channel} />
          </View>
          <View style={styles.dateContainer}>
            <Typography
              variant="xs"
              numberOfLines={1}
              color={showBadge ? theme.brand[500] : theme.text.neutral.lighter}>
              {date}
            </Typography>
            <View style={styles.indicatorsWrapper}>
              {isMuted && (
                <IconBellOff
                  size={SPACING.x2}
                  color={theme.text.neutral.default}
                  // Improve accessibility to muted
                  accessibilityLabel={t('chat.mute.mute')}
                />
              )}
              {isPinned && (
                <IconPin size={SPACING.x2} color={theme.text.neutral.default} />
              )}
              {showMentioned && (
                <IconAt
                  size={SPACING.x2}
                  color={theme.brand[500]}
                  // Improve accessibility by creating a label in hu-translations
                  accessibilityLabel="@"
                  testID="mentioned-icon"
                />
              )}
              <Badge
                show={showBadge}
                variant={chat.properties?.marked_unread_at ? 'info' : 'primary'}
                value={unread_count}
              />
            </View>
          </View>
        </View>
      </ListRow>
      <RightActions onMorePress={onRightActionsPress} />
    </RNSwipeable>
  );
}

export const ChatListItem = memo(
  ChatListItemComponent,
  (prevProps, nextProps) => {
    return (
      prevProps.chat.id === nextProps.chat.id &&
      prevProps.chat.latest?.ts === nextProps.chat.latest?.ts &&
      prevProps.chat.latest?.version === nextProps.chat.latest?.version &&
      prevProps.chat.latest?.text === nextProps.chat.latest?.text &&
      prevProps.chat.latest?.edited === nextProps.chat.latest?.edited &&
      prevProps.chat.latest?.status === nextProps.chat.latest?.status &&
      prevProps.chat.latest?.deliver_status?.read_at ===
        nextProps.chat.latest?.deliver_status?.read_at &&
      prevProps.chat.latest?.deliver_status?.received_at ===
        nextProps.chat.latest?.deliver_status?.received_at &&
      prevProps.chat.mentioned === nextProps.chat.mentioned &&
      prevProps.chat.properties?.pinned_at ===
        nextProps.chat.properties?.pinned_at &&
      prevProps.chat.properties?.notification_status?.notification_type ===
        nextProps.chat.properties?.notification_status?.notification_type &&
      prevProps.chat.properties?.marked_unread_at ===
        nextProps.chat.properties?.marked_unread_at
    );
  },
);
