import React, {
  ForwardedRef,
  LegacyRef,
  useEffect,
  useMemo,
  useState,
} from 'react';
import {
  Pressable,
  RefreshControlProps,
  View,
  FlatList as FlatListRN,
} from 'react-native';
import {useTranslation} from 'react-i18next';
import Animated from 'react-native-reanimated';
// Using this FlatList we can handle scroll events effectively in Android when rendered inside a Modal or Screen Modal
import {
  FlatList as FlatListGH,
  RefreshControl,
} from 'react-native-gesture-handler';
import {ListEmpty, Spinner} from '@components';
import {FlatListLayoutProps} from '@components/InfinityScrollFlatList/interfaces';
import Icon from '@components/Icon';
import SearchInput from '@components/SearchInput';
import Text from '@components/Text';
import {genericForwardRef} from '@components/InfinityScrollFlatList/utils';
import {useDebounce} from '@hooks/useDebounce';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {SEARCH_DELAY} from '@modules/group/constants';
import {COLORS} from '@shared/colors';
import {SPACING} from '@shared/theme';
import {DEFAULT_THRESHOLD} from '@shared/constants';

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

interface Props<TData, TFormattedData = TData>
  extends FlatListLayoutProps<TData, TFormattedData> {
  animated?: boolean;
  isError?: boolean;
  isFetchingNextPage?: boolean;
  isLoading?: boolean;
  isRefreshing?: boolean;
  onRefresh?: RefreshControlProps['onRefresh'];
}
type FlatListGHRef<T> = ForwardedRef<FlatListGH<T>> | undefined;
type FlatListRNRef<T> = ForwardedRef<FlatListRN<T>> | undefined;

const commonKeyExtractor = (_: unknown, index: number) => index.toString();

function FlatListLayoutForwardedRef<TData, TFormattedData = TData>(
  {
    ListEmptyComponent,
    ListHeaderComponent,
    ListErrorComponent,
    isRefreshing,
    onRefresh,
    isFetchingNextPage,
    isLoading,
    isError,
    data,
    formatData,
    contentContainerStyle,
    filterable,
    onFilterText,
    searchPlaceholder,
    keyExtractor,
    containerStyle,
    hitSlop,
    onPressFilterIcon,
    withFilterIcon = false,
    appliedFilters,
    animated,
    scrollEnabledOnEmpty = true,
    ...props
  }: Props<TFormattedData>,
  ref: FlatListGHRef<TFormattedData> | FlatListRNRef<TFormattedData>,
) {
  const {t} = useTranslation();
  const paddingBottom = useSafeAreaBottomPadding();
  const [searchValue, setSearchValue] = useState('');
  const debouncedSearchValue = useDebounce(searchValue, SEARCH_DELAY);
  const onChange = (searchText: string) => {
    setSearchValue(searchText);
  };

  useEffect(() => {
    onFilterText?.(debouncedSearchValue);
  }, [debouncedSearchValue, onFilterText]);

  const formattedData = useMemo(
    () => (formatData && data ? formatData(data) : data),
    [data, formatData],
  );

  const scrollEnabled =
    (formattedData && formattedData.length > 0) || scrollEnabledOnEmpty;

  return (
    <View style={[styles.container, containerStyle]}>
      <View style={styles.searchInputContainer}>
        {filterable && onFilterText && (
          <SearchInput
            style={styles.searchInput}
            withClose={!!searchValue.length}
            value={searchValue}
            onChange={onChange}
            placeholder={searchPlaceholder || t('general.search')}
          />
        )}
        {withFilterIcon && onPressFilterIcon && (
          <Pressable
            style={styles.iconContainer}
            onPress={onPressFilterIcon}
            hitSlop={SPACING['x1.5']}>
            {!!appliedFilters && (
              <View style={styles.bubbleContainer}>
                <Text variant="caption" color={COLORS.WHITE}>
                  {appliedFilters}
                </Text>
              </View>
            )}
            <Icon name="filterList" />
          </Pressable>
        )}
      </View>
      {animated ? (
        <Animated.FlatList
          {...props}
          CellRendererComponent={undefined}
          ref={ref as FlatListRNRef<TFormattedData>}
          hitSlop={hitSlop!}
          data={formattedData}
          contentContainerStyle={[
            styles.content,
            {paddingBottom},
            contentContainerStyle,
          ]}
          showsVerticalScrollIndicator={false}
          refreshControl={
            <RefreshControl
              refreshing={!!isRefreshing}
              onRefresh={onRefresh}
              tintColor={COLORS.PRIMARY}
              colors={[COLORS.PRIMARY]}
            />
          }
          keyExtractor={keyExtractor || commonKeyExtractor}
          onEndReachedThreshold={DEFAULT_THRESHOLD}
          ListFooterComponent={isFetchingNextPage ? <Spinner /> : null}
          ListEmptyComponent={
            !isLoading
              ? isError
                ? ListErrorComponent || ErrorList
                : ListEmptyComponent || (
                    <ListEmpty
                      title={t('general.empty')}
                      style={styles.emptyList}
                    />
                  )
              : null
          }
          ListHeaderComponent={isLoading ? <Spinner /> : ListHeaderComponent}
          scrollEnabled={scrollEnabled}
        />
      ) : (
        <FlatListGH
          {...props}
          ref={ref as LegacyRef<FlatListGH<TFormattedData>>}
          hitSlop={hitSlop!}
          data={formattedData}
          contentContainerStyle={[
            styles.content,
            {paddingBottom},
            contentContainerStyle,
          ]}
          showsVerticalScrollIndicator={false}
          refreshControl={
            <RefreshControl
              refreshing={!!isRefreshing}
              onRefresh={onRefresh}
              tintColor={COLORS.PRIMARY}
              colors={[COLORS.PRIMARY]}
            />
          }
          keyExtractor={keyExtractor || commonKeyExtractor}
          onEndReachedThreshold={DEFAULT_THRESHOLD}
          ListFooterComponent={isFetchingNextPage ? <Spinner /> : null}
          ListEmptyComponent={
            !isLoading
              ? isError
                ? ListErrorComponent || ErrorList
                : ListEmptyComponent || (
                    <ListEmpty
                      title={t('general.empty')}
                      style={styles.emptyList}
                    />
                  )
              : null
          }
          ListHeaderComponent={isLoading ? <Spinner /> : ListHeaderComponent}
          scrollEnabled={scrollEnabled}
        />
      )}
    </View>
  );
}

/**
 * @deprecated Use `_HuGo/List` instead
 */
export const FlatListLayout = genericForwardRef(FlatListLayoutForwardedRef);
