import React, {memo, useCallback, useMemo, useState} from 'react';
import {ListRenderItem, Pressable, StyleSheet, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {FormProvider} from 'react-hook-form';
import {useNavigation} from '@react-navigation/native';
import {IconCamera, IconPhoto} from '@tabler/icons-react-native';
import {
  Avatar,
  Button,
  InputClassicController,
  InputTextAreaController,
  List,
  ListItem,
  Menu,
  Typography,
} from '@components';
import {User} from '@interfaces/user';
import {Navigation} from '@interfaces/navigation';
import {
  CreateGroupForm,
  useCreateGroup,
  useCreateGroupForm,
  useSelectAttachment,
} from '@modules/chat/hooks';
import {BORDER_RADIUS, SPACING} from '@shared/theme';
import {getShortName, wait} from '@shared/utils';
import {Screens} from '@shared/constants';

interface Props {
  users: User[];
  onBack: () => void;
}

interface MenuItem {
  key: string;
  label: string;
  icon: React.FC;
}

const CreateGroupTab = ({users, onBack}: Props) => {
  const {t} = useTranslation();
  const [isMenuVisible, setIsMenuVisible] = useState(false);
  const navigation = useNavigation<Navigation['navigation']>();
  const userIds = useMemo(() => users.map(user => user.id), [users]);
  const {takePicture, selectPicture} = useSelectAttachment();
  const methods = useCreateGroupForm({
    initialValues: {memberIds: userIds},
  });
  const {createGroup, isLoading} = useCreateGroup({
    onSuccess: chatId => {
      navigation.replace(Screens.CHAT_DETAIL, {
        chatId,
      });
    },
  });
  const menuOptions: MenuItem[] = [
    {key: 'camera', label: t('general.take_picture'), icon: IconCamera},
    {key: 'gallery', label: t('general.select_photo'), icon: IconPhoto},
  ];
  const lastItemIndex = (users?.length || 0) - 1;
  const picture = methods.watch('picture');

  const onCreatePress = (formValues: CreateGroupForm) => {
    createGroup({
      ...formValues,
      userIds,
    });
  };

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

  const renderItem: ListRenderItem<User> = useCallback(
    ({item, index}) => {
      const name = getShortName(item);

      return (
        <ListItem
          title={name}
          avatar={{
            name,
            url: item.profilePicture,
          }}
          presentation="card"
          isFirstItem={index === 0}
          isLastItem={index === lastItemIndex}
        />
      );
    },
    [lastItemIndex],
  );

  const closeMenu = () => setIsMenuVisible(false);

  const onProfilePicturePress = () => setIsMenuVisible(true);

  const onMenuItemPress = (key: string) => async () => {
    try {
      closeMenu();

      // This is necessary to avoid ios bugs when open the select picture native modal
      await wait(250);

      const attachment = await (key === 'camera'
        ? takePicture()
        : selectPicture());

      methods.setValue('picture', attachment);
    } catch (error) {
      // Do nothing
    }
  };

  const renderMenuItem: ListRenderItem<MenuItem> = ({item}) => {
    return (
      <ListItem
        avatar={{Icon: item.icon}}
        title={item.label}
        onItemPress={onMenuItemPress(item.key)}
        presentation="flat"
        style={styles.menuItem}
      />
    );
  };

  const onBackPress = () => {
    methods.reset();
    onBack();
  };

  return (
    <>
      <View style={styles.container}>
        <View style={styles.header}>
          <Button
            variant="flat"
            text={t('general.back')}
            onPress={onBackPress}
          />
          <Typography variant="m" weight="semiBold">
            {t('chat.groups.new_group')}
          </Typography>
          <Button
            variant="flat"
            text={t('general.create')}
            onPress={methods.handleSubmit(onCreatePress)}
            isLoading={isLoading}
          />
        </View>
        <List
          data={users}
          renderItem={renderItem}
          keyExtractor={keyExtractor}
          withRefresh={false}
          bounces={false}
          ListHeaderComponent={
            <>
              <View style={styles.cardContainer}>
                <FormProvider {...methods}>
                  <Pressable
                    onPress={onProfilePicturePress}
                    style={styles.profilePictureContainer}>
                    <Avatar
                      url={picture?.url}
                      Icon={IconCamera}
                      variant="primary"
                      size="lg"
                    />
                  </Pressable>
                  <InputClassicController
                    label={t('chat.groups.group_name')}
                    name="title"
                  />
                  <InputTextAreaController
                    label={t('chat.groups.group_info')}
                    name="description"
                  />
                </FormProvider>
              </View>
              <Typography weight="semiBold" style={styles.membersTitle}>
                {t('chat.groups.members_title')}
              </Typography>
            </>
          }
        />
      </View>
      <Menu
        isVisible={isMenuVisible}
        onClose={closeMenu}
        data={menuOptions}
        renderItem={renderMenuItem}
        title={t('chats.add_profile_picture')}
        snapPoints={['30%']}
        scrollEnabled={false}
      />
    </>
  );
};

const styles = StyleSheet.create({
  container: {flex: 1},
  header: {
    padding: SPACING.x2,
    paddingTop: SPACING.x3,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  cardContainer: {
    gap: SPACING.x2,
  },
  membersTitle: {
    paddingHorizontal: SPACING.x2,
    marginVertical: SPACING.x2,
  },
  profilePictureContainer: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  menuItem: {
    borderRadius: BORDER_RADIUS.m,
    marginBottom: SPACING.x1,
  },
});

export default memo(CreateGroupTab);
