import React, {memo, useCallback, useState} from 'react';
import {ListRenderItem, ScrollView, StyleSheet, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {QueryKey} from 'react-query';
import {IconX} from '@tabler/icons-react-native';
import {
  Avatar,
  Button,
  CardContainer,
  Check,
  IconButton,
  InputSearch,
  List,
  ListItem,
  Typography,
} from '@components';
import {PageLimitQueryFn} from '@config/api';
import {useInfiniteQuery} from '@hooks/queries/useInfiniteQuery';
import {useDebounceCallback} from '@hooks/useDebounceCallback';
import {User} from '@interfaces/user';
import {SPACING} from '@shared/theme';
import {getShortName} from '@shared/utils';

interface Props {
  onCancel?: () => void;
  onNext?: (users: User[]) => void;
  nextLabel?: string;
  queryKey: (search: string) => QueryKey;
  queryFn: (search: string) => PageLimitQueryFn<User>;
}

const SelectChatMembers = ({
  onCancel,
  onNext,
  nextLabel,
  queryKey,
  queryFn,
}: Props) => {
  const {t} = useTranslation();
  const [searchText, setSearchText] = useState('');
  const [selectedUsers, setSelectedUsers] = useState<User[]>([]);

  const {
    data,
    isLoading,
    isError,
    getNextPage,
    isRefreshing,
    hasNextPage,
    isFetchingNextPage,
  } = useInfiniteQuery(queryKey(searchText), queryFn(searchText));
  const lastItemIndex = (data?.length || 0) - 1;

  const {debouncedCallback: debounceSearch} = useDebounceCallback(
    (text: string) => {
      setSearchText(text);
    },
  );

  const removeSelection = useCallback((id: number) => {
    setSelectedUsers(current => current.filter(item => item.id !== id));
  }, []);

  const addSelection = useCallback((item: User) => {
    setSelectedUsers(current => [...current, item]);
  }, []);

  const onNextPress = () => {
    onNext?.(selectedUsers);
  };

  const keyExtractor = useCallback((item: User) => item.id.toString(), []);

  const renderItem: ListRenderItem<User> = useCallback(
    ({item, index}) => {
      const name = getShortName(item);
      const selected = selectedUsers.some(user => user.id === item.id);
      const onPress = () =>
        selected ? removeSelection(item.id) : addSelection(item);

      return (
        <ListItem
          title={name}
          avatar={{
            name,
            url: item.profilePicture,
          }}
          presentation="card"
          isFirstItem={index === 0}
          isLastItem={index === lastItemIndex}
          onItemPress={onPress}>
          <Check checked={selected} pointerEvents="none" />
        </ListItem>
      );
    },
    [addSelection, lastItemIndex, removeSelection, selectedUsers],
  );

  return (
    <View style={styles.container}>
      <View style={styles.header}>
        <Button variant="flat" text={t('general.cancel')} onPress={onCancel} />
        <Typography variant="m" weight="semiBold">
          {t('chats.add_members')}
        </Typography>
        <Button
          variant="flat"
          text={nextLabel || t('general.next')}
          onPress={onNextPress}
          disabled={!selectedUsers.length}
        />
      </View>
      <View style={styles.subHeader}>
        <InputSearch
          value={searchText}
          placeholder={t('chat.search.by_name')}
          onChangeText={debounceSearch}
        />
        {!!selectedUsers.length && (
          <CardContainer style={styles.withoutPadding}>
            <ScrollView
              horizontal
              contentContainerStyle={styles.selectedItems}
              showsHorizontalScrollIndicator={false}>
              {selectedUsers.map(user => {
                const name = getShortName(user);
                return (
                  <View key={user.id} style={styles.selectedItem}>
                    <View>
                      <Avatar name={name} url={user.profilePicture} size="lg" />
                      <View style={styles.selectedRemoveButton}>
                        <IconButton
                          Icon={IconX}
                          size="sm"
                          onPress={() => removeSelection(user.id)}
                        />
                      </View>
                    </View>
                    <Typography numberOfLines={1}>{name}</Typography>
                  </View>
                );
              })}
            </ScrollView>
          </CardContainer>
        )}
      </View>
      <List
        presentation="card"
        data={data}
        isLoading={isLoading}
        isError={isError}
        isRefreshing={isRefreshing}
        keyExtractor={keyExtractor}
        renderItem={renderItem}
        onNextPage={getNextPage}
        hasNextPage={hasNextPage}
        isFetchingNextPage={isFetchingNextPage}
        paginationType="button"
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {flex: 1},
  header: {
    padding: SPACING.x2,
    paddingTop: SPACING.x3,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  subHeader: {
    paddingHorizontal: SPACING.x2,
    gap: SPACING.x2,
    marginBottom: SPACING.x2,
  },
  selectedItem: {
    justifyContent: 'center',
    alignItems: 'center',
    width: 80,
  },
  selectedRemoveButton: {position: 'absolute', top: 0, right: 0},
  selectedItems: {gap: SPACING.x2, paddingHorizontal: SPACING.x2},
  withoutPadding: {paddingHorizontal: -SPACING.x2},
});

export default memo(SelectChatMembers);
