import React, {ForwardedRef, LegacyRef, ReactNode, useCallback} from 'react';
import {
  SectionListProps as SectionListRNProps,
  RefreshControl,
  SectionList as SectionListRN,
  View,
} from 'react-native';
import {useTranslation} from 'react-i18next';
import {Divider} from '@components/_HuGo/Divider';
import {ListEmpty} from '@components/_HuGo/List';
import {Spinner} from '@components/_HuGo/Spinner';
import {DEFAULT_THRESHOLD} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {genericForwardRef} from '@shared/utils';

import {SectionListSkeleton} from '../SectionListSkeleton';
import {styles} from './styles';

const ItemSeparator = () => <Divider style={styles.divider} />;

type SectionListRNRef<T> = ForwardedRef<SectionListRN<T>> | undefined;

// TODO: check with design if any change is needed
export interface SectionListProps<TData>
  extends Pick<
    SectionListRNProps<TData>,
    | 'sections'
    | 'keyExtractor'
    | 'renderItem'
    | 'renderSectionHeader'
    | 'ListEmptyComponent'
    | 'style'
    | 'bounces'
    | 'scrollEnabled'
    | 'ListHeaderComponent'
    | 'onEndReachedThreshold'
    | 'getItemLayout'
    | 'ItemSeparatorComponent'
    | 'showsVerticalScrollIndicator'
    | 'keyboardDismissMode'
    | 'keyboardShouldPersistTaps'
    | 'onScroll'
    | 'stickySectionHeadersEnabled'
  > {
  backgroundColor?: string;
  isLoading?: boolean;
  isError?: boolean;
  isRefreshing?: boolean;
  hasNextPage?: boolean;
  onNextPage?: () => void;
  onRefresh?: () => void;
  errorText?: string;
  emptyText?: string;
  IconEmptyList?: ReactNode;
  titleEmptyList?: string;
  descriptionEmptyList?: string;
  withDivider?: boolean;
  withRefresh?: boolean;
  FetchingNextPageLoader?: ReactNode;
}

const defaultKeyExtractor = (item: unknown, index: number) =>
  `${(item as {id: number})?.id}- ${index}`;

export function SectionListForwaredRef<TData>(
  {
    backgroundColor,
    sections,
    isLoading,
    isError,
    hasNextPage,
    isRefreshing,
    onNextPage,
    onRefresh,
    errorText,
    emptyText,
    ListEmptyComponent,
    style,
    renderItem,
    renderSectionHeader,
    IconEmptyList,
    titleEmptyList,
    descriptionEmptyList,
    withRefresh = true,
    withDivider,
    bounces = true,
    scrollEnabled = true,
    onEndReachedThreshold = DEFAULT_THRESHOLD,
    FetchingNextPageLoader,
    keyExtractor = defaultKeyExtractor,
    ...props
  }: SectionListProps<TData>,
  ref: SectionListRNRef<TData>,
) {
  const {t} = useTranslation();
  const {theme} = useTheme();
  const listEmptyText = isError
    ? errorText || t('errors.api.500', {info: ''})
    : emptyText || t('general.empty');

  const onEndReached = useCallback(() => {
    onNextPage?.();
  }, [onNextPage]);

  return (
    <SectionListRN
      ref={ref as LegacyRef<SectionListRN<TData>>}
      sections={sections}
      keyExtractor={keyExtractor}
      renderItem={renderItem}
      renderSectionHeader={renderSectionHeader}
      ItemSeparatorComponent={withDivider ? ItemSeparator : null}
      onEndReachedThreshold={onEndReachedThreshold}
      onEndReached={onEndReached}
      bounces={bounces}
      scrollEnabled={scrollEnabled}
      contentContainerStyle={style}
      refreshControl={
        withRefresh ? (
          <RefreshControl
            refreshing={!!isRefreshing}
            onRefresh={onRefresh}
            tintColor={theme.neutralIlus}
            colors={[theme.neutralIlus]}
          />
        ) : undefined
      }
      ListEmptyComponent={
        ListEmptyComponent ||
        (isLoading ? (
          <SectionListSkeleton />
        ) : (
          <ListEmpty
            title={titleEmptyList || listEmptyText}
            description={descriptionEmptyList}
            IconComponent={IconEmptyList}
          />
        ))
      }
      ListFooterComponent={
        <>
          {!isLoading &&
            hasNextPage &&
            (FetchingNextPageLoader || (
              <View style={styles.spinner}>
                <Spinner />
              </View>
            ))}
        </>
      }
      style={{backgroundColor}}
      {...props}
    />
  );
}

export const SectionList = genericForwardRef(SectionListForwaredRef);
