import { type CSSProperties, type FC, useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';

import {
  LegendList,
  type LegendListRenderItemProps,
} from '@legendapp/list/react';
import Stack from '@material-hu/mui/Stack';

import { logEvent } from 'src/config/amplitude';
import { useAuth } from 'src/contexts/JWTContext';
import { useStableCallback } from 'src/hooks/useStableCallback';
import {
  CONVERSATION_TYPE,
  CONVERSATIONS_LIST_CONTAINER,
  CONVERSATIONS_LIST_DIVIDER_STACK_SX,
} from 'src/pages/dashboard/Conversations/constants';
import { type Channel } from 'src/pages/dashboard/Conversations/types';
import { EventName } from 'src/types/amplitude';
import { useLokaliseTranslation } from 'src/utils/i18n';

import NoResults from 'src/components/list/NoResults';

import ConversationItem from './ConversationItem';
import ConversationsSkeleton from './ConversationsSkeleton';
import {
  useConversationList,
  useGetPinnedCount,
} from '../../hooks/useConversationsQueries';
import { conversationsRoutes } from '../../routes';

const getFixedItemSize = () => 75;

const styles: Record<string, CSSProperties> = {
  list: {
    flex: 1,
    height: '100%',
    width: '100%',
  },
  contentContainer: {
    paddingTop: 8,
  },
};

export const ConversationsList: FC = () => {
  const { t } = useLokaliseTranslation('chat');
  const navigate = useNavigate();
  const { user } = useAuth();
  const {
    conversations,
    hasNextPage,
    fetchNextPage,
    isFetchingNextPage,
    isSuccess: isConversationsSuccess,
    isLoading: conversationsLoading,
  } = useConversationList();
  const pinnedConversationsCount = useGetPinnedCount();

  const handleSelect = useCallback(
    (conversation: Channel) => {
      const isGroupConversation = Boolean(conversation?.is_channel);
      const eventProperties = {
        userId: user?.id.toString(),
        conversationType: isGroupConversation
          ? CONVERSATION_TYPE.GROUP
          : CONVERSATION_TYPE.INDIVIDUAL,
        conversationID: conversation.id,
      };
      logEvent(EventName.CHATS_2_CONVERSATION_OPENED, eventProperties);

      navigate(conversationsRoutes.thread.detail(conversation.id));
    },
    [navigate, user?.id],
  );

  const isEmpty = !conversations?.length && !conversationsLoading;
  const hasMoreConversations = hasNextPage || false;

  const listData = isConversationsSuccess ? conversations : [];
  const extraData = useMemo(
    () => ({ pinnedConversationsCount }),
    [pinnedConversationsCount],
  );

  const onEndReached = useCallback(() => {
    if (!hasMoreConversations || isFetchingNextPage || conversationsLoading) {
      return;
    }
    fetchNextPage?.();
  }, [
    fetchNextPage,
    hasMoreConversations,
    isFetchingNextPage,
    conversationsLoading,
  ]);

  const keyExtractor = useCallback(
    (conversation: Channel) => conversation.id,
    [],
  );

  const renderConversationItem = useStableCallback(
    ({ item }: LegendListRenderItemProps<Channel>) => (
      <ConversationItem
        onClick={({ conversation }) =>
          conversation && handleSelect(conversation)
        }
        conversation={item}
        pinnedConversationsCount={pinnedConversationsCount}
      />
    ),
  );

  const listEmptyComponent = useMemo(() => {
    if (conversationsLoading) {
      return <ConversationsSkeleton />;
    }
    if (isConversationsSuccess && isEmpty) {
      return <NoResults label={t('no_conversations')} />;
    }
    return null;
  }, [isEmpty, conversationsLoading, isConversationsSuccess, t]);

  const listFooterComponent = useMemo(
    () => (isFetchingNextPage ? <ConversationsSkeleton /> : null),
    [isFetchingNextPage],
  );

  return (
    <Stack
      sx={{
        overflow: 'hidden',
        flex: 1,
        ...CONVERSATIONS_LIST_DIVIDER_STACK_SX,
      }}
    >
      <LegendList
        id={CONVERSATIONS_LIST_CONTAINER}
        data={listData}
        drawDistance={1000}
        extraData={extraData}
        keyExtractor={keyExtractor}
        renderItem={renderConversationItem}
        ListEmptyComponent={listEmptyComponent}
        ListFooterComponent={listFooterComponent}
        onEndReached={onEndReached}
        onEndReachedThreshold={0.1}
        style={styles.list}
        contentContainerStyle={styles.contentContainer}
        getFixedItemSize={getFixedItemSize}
      />
    </Stack>
  );
};

export default ConversationsList;
