import React, {useCallback, useEffect, useState} from 'react';
import {View, TouchableOpacity, FlatList, ListRenderItem} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useDispatch} from 'react-redux';
import {useMutation} from 'react-query';
import AcceptCancelDialog from '@components/AcceptCancelDialog';
import AddUsersButton from '@components/AddUsersButton';
import Icon from '@components/Icon';
import Text from '@components/Text';
import ActivityIndicator from '@components/ActivityIndicator';
import {useSafeAreaBottomPadding} from '@hooks/useSafeAreaBottomPadding';
import {Navigation} from '@interfaces/navigation';
import {User} from '@interfaces/user';
import {
  makeAdminOfGroupChat,
  removeUserFromGroupChat,
  leaveGroupChat,
  updateChat as updateChatService,
} from '@modules/chat/services';
import {GroupChatListItem} from '@modules/chat/interfaces';
import {useGetChatDetail} from '@modules/chat/hooks';
import {removeChat, updateChat} from '@modules/chat/redux';
import {useAppSelector} from '@redux/utils';
import {getCompleteName, getDate, logAmplitudeEvent} from '@shared/utils';
import {AMPLITUDE_EVENTS, Screens} from '@shared/constants';
import {COLORS} from '@shared/colors';
import {SHARED_STRINGS} from '@shared/strings';

import {styles} from './styles';
import GroupUser from './components/GroupUser';
import GroupInformation from './components/GroupInformation';

export function GroupInfo({
  navigation,
  route: {
    params: {chatId},
  },
}: Navigation<Screens.CHAT_GROUP_INFO>) {
  const {t} = useTranslation();
  const dispatch = useDispatch();
  const paddingBottom = useSafeAreaBottomPadding();
  const userId = useAppSelector(({user}) => user.id);
  const [showExitDialog, setShowExitDialog] = useState(false);
  const [removableParticipant, setRemovableParticipant] =
    useState<Nullable<User>>(null);
  const [adminParticipant, setAdminParticipant] =
    useState<Nullable<User>>(null);
  const [selectedUser, setSelectedUser] = useState<Nullable<number>>(null);
  const [shouldRemoveChat, setShouldRemoveChat] = useState(false);
  const {
    chat: chatDetail,
    getUsersNextPage,
    isUsersFetchingNextPage,
    isUsersRefreshing,
    totalParticipants,
  } = useGetChatDetail({chatId});
  const chat = chatDetail as GroupChatListItem;
  const iAmAdmin = chat.isAdmin;

  const toggleMuteChatMutation = useMutation(
    () => updateChatService({userId, chatId, muted: !chat.chat.muted}),
    {
      onSuccess: ({chat: {muted}}) => {
        dispatch(
          updateChat({
            chatId,
            muted: muted || undefined,
          }),
        );
      },
    },
  );

  const removeParticipant = useMutation(removeUserFromGroupChat, {
    onSuccess: (_data, {userId: deletedUserId}) => {
      dispatch(
        updateChat({
          chatId,
          otherUsers: chat.chat.otherUsers?.filter(
            user => user.id !== deletedUserId,
          ),
        }),
      );
    },
  });
  const makeAdmin = useMutation(makeAdminOfGroupChat, {
    onSuccess: (_data, {userId: adminUserId}) => {
      dispatch(
        updateChat({
          chatId,
          otherUsers: chat.chat.otherUsers?.map(user =>
            user.id === adminUserId ? {...user, isAdmin: true} : user,
          ),
        }),
      );
    },
  });
  const exitGroup = useMutation(leaveGroupChat, {
    onSuccess: () => {
      setShowExitDialog(false);
      setShouldRemoveChat(true);
      logAmplitudeEvent(AMPLITUDE_EVENTS.CHAT_GROUP_LEAVE, {chatId});
      navigation.pop(2);
    },
    onError: () => {
      setShowExitDialog(false);
    },
  });

  const onAddUsers = useCallback(() => {
    navigation.navigate(Screens.CHAT_GROUP_ADD_MEMBERS, {
      chatId,
    });
  }, [chatId, navigation]);

  const keyExtractor = useCallback((item: User) => `${item.id}`, []);

  const renderItem: ListRenderItem<User> = useCallback(
    ({item}) => (
      <GroupUser
        user={item}
        iAmAdmin={iAmAdmin}
        selectedUser={selectedUser}
        onSetSelectUser={setSelectedUser}
        onSetRemovableParticipant={setRemovableParticipant}
        onSetAdminParticipant={setAdminParticipant}
      />
    ),
    [iAmAdmin, selectedUser],
  );

  useEffect(() => {
    return () => {
      shouldRemoveChat &&
        dispatch(removeChat({chatId, archived: chat.chat.archived}));
    };
  }, [chat.chat.archived, chatId, dispatch, shouldRemoveChat]);

  return (
    <>
      <FlatList
        keyboardShouldPersistTaps="handled"
        data={chat.chat.otherUsers}
        bounces={false}
        showsVerticalScrollIndicator={false}
        contentContainerStyle={[styles.container, {paddingBottom}]}
        ListHeaderComponent={
          <>
            <GroupInformation chat={chat} iAmAdmin={iAmAdmin} />
            <TouchableOpacity
              style={styles.notificationsContainer}
              onPress={() => toggleMuteChatMutation.mutate()}>
              <View style={styles.notificationsLeftContainer}>
                <Icon name="notifications" style={styles.bellContainer} />
                <Text>{t(SHARED_STRINGS.NOTIFICATIONS)}</Text>
              </View>
              <Text color={COLORS.LIGHT_BLUE_SIX}>
                {chat.chat.muted ? t(SHARED_STRINGS.NO) : t(SHARED_STRINGS.YES)}
              </Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={styles.exitButtonContainer}
              onPress={() => setShowExitDialog(true)}>
              <Icon
                name="logout"
                color={COLORS.RED}
                style={styles.iconContainer}
              />
              <Text color={COLORS.RED}>{t('chats.exit_group')}</Text>
            </TouchableOpacity>
            {chat.chat.otherUsers && (
              <View style={styles.participantsTitle}>
                <Text variant="subtitle1">
                  {`${t('chats.participants')} (${totalParticipants})`}
                </Text>
              </View>
            )}
            {iAmAdmin && (
              <AddUsersButton
                handlePress={onAddUsers}
                text={t('chats.add_participants')}
              />
            )}
          </>
        }
        renderItem={renderItem}
        ListFooterComponent={
          <>
            <ActivityIndicator isVisible={isUsersFetchingNextPage} />
            <View style={styles.bottomContainer}>
              <Text color={COLORS.DARK_GRAY}>
                {t('chats.group_created_on', {
                  createdOn: getDate(chat.createdAt),
                })}
              </Text>
            </View>
          </>
        }
        ListEmptyComponent={isUsersRefreshing ? <ActivityIndicator /> : null}
        keyExtractor={keyExtractor}
        onEndReached={getUsersNextPage}
      />
      <AcceptCancelDialog
        visible={showExitDialog}
        onTouchOutside={() => setShowExitDialog(false)}
        onAccept={() => exitGroup.mutate({chatId, userId})}
        showCancel
        title={t('chats.exit_group')}
        text={t('chats.exit_group_question')}
      />
      <AcceptCancelDialog
        visible={!!removableParticipant}
        onTouchOutside={() => setRemovableParticipant(null)}
        onAccept={() => {
          removeParticipant.mutate({
            chatId,
            userId: removableParticipant!.id,
          });
          setRemovableParticipant(null);
        }}
        showCancel
        title={t('chats.remove')}
        text={t('chats.remove_participant_question', {
          participant: removableParticipant
            ? getCompleteName(removableParticipant)
            : '',
        })}
      />
      <AcceptCancelDialog
        visible={!!adminParticipant}
        onTouchOutside={() => setAdminParticipant(null)}
        onAccept={() => {
          makeAdmin.mutate({chatId, userId: adminParticipant!.id});
          setAdminParticipant(null);
        }}
        showCancel
        title={t('chats.make_admin')}
        text={t('chats.make_admin_question', {
          participant: adminParticipant
            ? getCompleteName(adminParticipant)
            : '',
        })}
      />
    </>
  );
}
