/**
 * Filter by hashtags is implemented with array if in a future product decides to filter with more than one hashtag
 */
import React, {useCallback, useRef, useState} from 'react';
import {FlatList, NativeScrollEvent, ScrollView, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useDispatch} from 'react-redux';
import {useFocusEffect, useNavigation} from '@react-navigation/native';
import {useQuery} from 'react-query';
import {IconFilter, IconZoomExclamation} from '@tabler/icons-react-native';
import {
  AbsolutePill,
  Spinner,
  RefreshControl,
  ArticleSkeleton,
  Avatar,
  BadgeIconButton,
  Chip,
  InputSearch,
  ListEmpty,
} from '@components';
import i18next, {Language} from '@config/i18n';
import {useDebounce} from '@hooks/useDebounce';
import {usePersistedTimeStampInfiniteQuery} from '@hooks/queries/usePersistedTimeStampInfiniteQuery';
import {getArticles, getArticleTags} from '@modules/article/services';
import {
  ARTICLES_SEARCH_DEBOUNCE,
  ARTICLE_QUERY_KEYS,
} from '@modules/article/constants';
import {ArticleItem} from '@modules/article/components';
import {useArticlesListListener} from '@modules/article/hooks/useArticlesListListeners';
import {Article} from '@modules/article/interfaces';
import {setHasNewArticles} from '@modules/article/redux';
import {TagsFilterDialog} from '@modules/article/screens/Articles/components/TagsFilterDialog';
import {useAppSelector} from '@redux/utils';
import {DEFAULT_THRESHOLD, Screens} from '@shared/constants';
import {isCloseToTop, scrollToTopFlatList} from '@shared/utils';
import {useTheme} from '@shared/theme';
import {commonStyles} from '@shared/styles';

import {styles} from './styles';

const keyExtractor = (item: Article, index: number) =>
  `${item ? item.id : index}`;

const renderItem = ({item}: {item: Article}) => <ArticleItem article={item} />;

function Articles() {
  const navigation = useNavigation();
  const {t} = useTranslation();
  const dispatch = useDispatch();
  const {theme} = useTheme();
  const [tagsSelected, setTagsSelected] = useState<number[]>([]);
  const [isFilterModalVisible, setIsFilterModalVisible] = useState(false);
  const [searchValue, setSearchValue] = useState('');
  const debouncedSearch = useDebounce(
    searchValue.trim(),
    ARTICLES_SEARCH_DEBOUNCE,
  );
  const hasNewArticles = useAppSelector(({article}) => article.hasNewArticles);
  const moduleNames = useAppSelector(({instance}) => instance.moduleNames);
  const [closeToTop, setCloseToTop] = useState(true);
  const flatListRef = useRef<Nullable<FlatList<Article>>>(null);
  const i18nArticles =
    moduleNames?.[i18next.language as Language]?.ARTICLES || t('home.articles');
  const {data: tags, refetch: refetchTags} = useQuery(
    ARTICLE_QUERY_KEYS.getTags,
    getArticleTags,
  );
  const {
    data: articles,
    isLoading,
    isFetchingNextPage,
    getNextPage,
    refresh: refreshArticles,
    isRefreshing,
  } = usePersistedTimeStampInfiniteQuery<Article>({
    queryKey: ARTICLE_QUERY_KEYS.articleList(tagsSelected, debouncedSearch),
    queryFn: ({limit, timestamp}) =>
      getArticles({
        limit,
        timestamp,
        hashtags: tagsSelected,
        q: debouncedSearch,
      }),
  });

  useArticlesListListener(tagsSelected);

  const onOpenFilterModal = useCallback(() => {
    setIsFilterModalVisible(true);
  }, []);

  const onCloseFilterModal = useCallback(() => {
    setIsFilterModalVisible(false);
  }, []);

  const onConfirmFilter = useCallback((tagIds: number[]) => {
    setTagsSelected(tagIds);
  }, []);

  const onRemoveTag = (tagId: number) => () =>
    setTagsSelected(prev => prev.filter(id => id !== tagId));

  const refresh = useCallback(() => {
    refreshArticles();
    refetchTags();
  }, [refreshArticles, refetchTags]);

  const selectedTags = tags?.filter(tag => tagsSelected.includes(tag.id)) || [];
  const activeFiltersCount = tagsSelected.length;

  const checkNewArticles = useCallback(() => {
    dispatch(setHasNewArticles(false));
    scrollToTopFlatList(flatListRef);
    // TODO: SQPM-3612 Replace refetch to add socket data into query data
    refreshArticles();
  }, [dispatch, refreshArticles]);

  const onScroll = useCallback(
    ({nativeEvent}: {nativeEvent: NativeScrollEvent}) => {
      setCloseToTop(isCloseToTop(nativeEvent));
    },
    [],
  );

  // Side effect to set initial topic filter when user comes from ArticleDetail screen
  useFocusEffect(
    useCallback(() => {
      const topicId = (
        navigation
          .getState()
          ?.routes?.find?.(route => route.name === Screens.HOME)?.params as {
          topicId: number;
        }
      )?.topicId;
      if (topicId) {
        setTagsSelected([topicId]);
      }
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []),
  );

  return (
    <>
      {hasNewArticles && !closeToTop && (
        <AbsolutePill
          text={t('home.new_articles', {
            articles: i18nArticles,
          })}
          onPress={checkNewArticles}
        />
      )}
      <FlatList
        ref={flatListRef}
        style={commonStyles.flex}
        data={articles || []}
        refreshControl={
          <RefreshControl refreshing={isRefreshing} onRefresh={refresh} />
        }
        keyExtractor={keyExtractor}
        contentContainerStyle={[
          styles.listContent,
          {backgroundColor: theme.background.layout.default},
        ]}
        showsVerticalScrollIndicator={false}
        onEndReached={getNextPage}
        onEndReachedThreshold={DEFAULT_THRESHOLD}
        onScroll={onScroll}
        renderItem={renderItem}
        ListHeaderComponent={
          <View style={{backgroundColor: theme.background.layout.tertiary}}>
            <View style={styles.searchContainer}>
              <View style={commonStyles.flex}>
                <InputSearch
                  value={searchValue}
                  size="sm"
                  onChangeText={setSearchValue}
                  placeholder={t('general.search')}
                  variant="secondary"
                />
              </View>
              <BadgeIconButton
                Icon={IconFilter}
                onIconPress={onOpenFilterModal}
                value={activeFiltersCount}
                containerStyle={styles.filterButton}
                accessibilityLabel={t('general.filter')}
              />
            </View>
            {!!selectedTags.length && (
              <ScrollView
                horizontal
                showsHorizontalScrollIndicator={false}
                contentContainerStyle={styles.activeFilters}>
                {selectedTags.map(tag => (
                  <Chip
                    key={tag.id}
                    text={tag.name}
                    size="sm"
                    showCloseIcon
                    showActiveIcon={false}
                    onClose={onRemoveTag(tag.id)}
                  />
                ))}
              </ScrollView>
            )}
          </View>
        }
        ListEmptyComponent={
          isLoading || articles === undefined ? (
            <View style={styles.gap}>
              <ArticleSkeleton />
              <ArticleSkeleton />
            </View>
          ) : (
            <View
              style={[
                {backgroundColor: theme.background.layout.tertiary},
                commonStyles.flex,
              ]}>
              <ListEmpty
                title={
                  debouncedSearch
                    ? t('general.empty_search_result')
                    : t('home.no_articles', {
                        articles: i18nArticles!.toLowerCase(),
                      })
                }
                IconComponent={
                  <Avatar
                    variant="primary"
                    Icon={IconZoomExclamation}
                    size="lg"
                  />
                }
              />
            </View>
          )
        }
        ListFooterComponent={isFetchingNextPage ? <Spinner /> : null}
      />
      <TagsFilterDialog
        isVisible={isFilterModalVisible}
        tags={tags}
        tagsSelected={tagsSelected}
        onClose={onCloseFilterModal}
        onConfirm={onConfirmFilter}
      />
    </>
  );
}

export default Articles;
