import React, {memo, useCallback, useMemo, useState} from 'react';
import {SectionList, SectionListRenderItem, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {IconZoomExclamation} from '@tabler/icons-react-native';
import {useNetInfo} from '@react-native-community/netinfo';
import {BottomSheetSectionList} from '@gorhom/bottom-sheet';
import {Divider, ListFooter, ListSkeleton, Skeleton, Title} from '@components';
import {useDebounce} from '@hooks/useDebounce';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {UserPermissions} from '@interfaces/user';
import {ChatEmptyState} from '@modules/chats/components';
import {useSearchUsers, useSearchConversations} from '@modules/chats/hooks';
import {ChatUser, Conversation} from '@modules/chats/interfaces';
import {getChatItemLayout} from '@modules/chats/utils';
import {useIsFetchingEvents} from '@modules/chats/store';
import {usePermission} from '@redux/selectors';
import {SPACING} from '@shared/theme';

import {ChatLoadMoreButton} from './components/ChatLoadMoreButton';
import {styles} from './styles';

const SEARCH_CONVERSATIONS_LIMIT = 5;

const keyExtractor = (item: Conversation | ChatUser) => `${item.id}`;

const ItemSeparator = (data: {section: ChatSearchSection}) => {
  return (
    <Divider
      style={
        data.section.type === 'users'
          ? styles.dividerUserItem
          : styles.dividerChatItem
      }
    />
  );
};

export type ChatSearchSection =
  | {
      type: 'chats';
      title: string;
      data: Conversation[];
    }
  | {
      type: 'users';
      title: string;
      data: ChatUser[];
    };

interface Props {
  searchText: string;
  renderItem: SectionListRenderItem<Conversation | ChatUser, ChatSearchSection>;
  freezeConversations?: boolean;
  useBottomSheetSectionList?: boolean;
  withoutDeactivatedUsers?: boolean;
}

function ChatSearchCmp({
  searchText,
  renderItem,
  freezeConversations,
  useBottomSheetSectionList = false,
  withoutDeactivatedUsers,
}: Props) {
  const {t} = useTranslation();
  const canCreateConversation = usePermission(
    UserPermissions.CHATS_V2_CREATE_CONVERSATION,
  );
  const paddingBottom = useSafeAreaBottomPadding({extra: 250});
  const debouncedSearchText = useDebounce(searchText, 250, '');
  const [showAllConversations, setShowAllConversations] = useState(false);
  const {isInternetReachable} = useNetInfo();
  const conversations = useSearchConversations({
    searchText: debouncedSearchText,
    freeze: freezeConversations,
    withoutDeactivatedUsers,
  });
  const isFetchingEvents = useIsFetchingEvents();
  const totalConversations = conversations.length;
  const conversationsWithLimit = showAllConversations
    ? conversations
    : conversations.slice(0, SEARCH_CONVERSATIONS_LIMIT);
  const VirtualizedList = useMemo(() => {
    return useBottomSheetSectionList ? BottomSheetSectionList : SectionList;
  }, [useBottomSheetSectionList]);

  const {
    users,
    isLoading: usersIsLoading,
    getNextPage: usersGetNextPage,
    hasNextPage: usersHasNextPage,
    isFetchingNextPage: usersIsFetchingNextPage,
  } = useSearchUsers({
    search: debouncedSearchText,
    enabled:
      !!isInternetReachable && !isFetchingEvents && canCreateConversation,
  });

  const sections: ChatSearchSection[] = useMemo(() => {
    return [
      !conversationsWithLimit?.length
        ? null
        : {
            type: 'chats',
            title: t('chat.chats'),
            data: conversationsWithLimit || [],
          },
      !canCreateConversation || !users?.length
        ? null
        : {
            type: 'users',
            title: t('chat.users'),
            data: users || [],
          },
    ].filter(Boolean) as ChatSearchSection[];
  }, [canCreateConversation, conversationsWithLimit, t, users]);

  const getMoreConversations = useCallback(() => {
    setShowAllConversations(true);
  }, []);

  const renderSectionFooter = useCallback(
    ({section}: {section: ChatSearchSection}) => {
      if (section.data.length === 0) {
        return (
          <ListSkeleton
            presentation="flat"
            itemLength={
              section.type === 'chats' ? SEARCH_CONVERSATIONS_LIMIT : 10
            }
          />
        );
      }
      if (section.type === 'chats') {
        return totalConversations > SEARCH_CONVERSATIONS_LIMIT &&
          !showAllConversations ? (
          <ChatLoadMoreButton
            text={t('chat.show_more')}
            onPress={getMoreConversations}
          />
        ) : null;
      } else {
        return (
          <ListFooter
            isVisible={usersIsFetchingNextPage}
            isFetchingNextPage={usersIsFetchingNextPage}
            paginationType="infiniteScroll"
            FetchingNextPageLoader={
              <ListSkeleton presentation="flat" withDivider />
            }
          />
        );
      }
    },
    [
      getMoreConversations,
      showAllConversations,
      t,
      totalConversations,
      usersIsFetchingNextPage,
    ],
  );

  const renderSectionHeader = useCallback(
    ({section}: {section: ChatSearchSection}) => (
      <Title style={styles.sectionTitle} title={section.title} />
    ),
    [],
  );

  const onEndReached = useCallback(() => {
    if (!usersIsLoading && usersHasNextPage) {
      usersGetNextPage();
    }
  }, [usersIsLoading, usersHasNextPage, usersGetNextPage]);

  const ListEmptyComponent = useMemo(() => {
    if (!debouncedSearchText || (canCreateConversation && usersIsLoading)) {
      return (
        <>
          <Skeleton style={styles.skeletonContainer}>
            <Skeleton.Item width="100%" height={SPACING.x3} />
          </Skeleton>
          <ListSkeleton presentation="flat" />
        </>
      );
    }
    return (
      <ChatEmptyState
        icon={IconZoomExclamation}
        title={t('chat.search.not_found_title')}
        description={t('chat.search.not_found_subtitle')}
        style={styles.emptyState}
      />
    );
  }, [canCreateConversation, debouncedSearchText, t, usersIsLoading]);

  return (
    <View style={styles.container}>
      <VirtualizedList
        keyboardDismissMode="on-drag"
        keyboardShouldPersistTaps="handled"
        sections={sections}
        contentContainerStyle={[styles.contentContainer, {paddingBottom}]}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
        renderSectionHeader={renderSectionHeader}
        getItemLayout={getChatItemLayout}
        stickySectionHeadersEnabled={false}
        onEndReached={onEndReached}
        renderSectionFooter={renderSectionFooter}
        ListEmptyComponent={ListEmptyComponent}
        ItemSeparatorComponent={ItemSeparator}
      />
    </View>
  );
}

export const ChatSearch = memo(ChatSearchCmp);
