import React, {
  memo,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import {View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useNavigation} from '@react-navigation/native';
import {FlatList} from 'react-native-gesture-handler';
import {
  Dialog,
  ListItem,
  RenderSceneProps,
  Spinner,
  TabItem,
  Tabs,
  TabsRef,
} from '@components';
import {useBackHandler} from '@hooks/useBackHandler';
import {useReactionDialog, useReactionList} from '@modules/chats/store';
import {HuDataMember} from '@modules/chats/interfaces';
import {getUserAvatar} from '@modules/chats/utils';
import {persistedUserId} from '@services/localStorage';
import {Screens} from '@shared/constants';

import {getItemLayout, styles} from './styles';

const snapPoints = ['50%'];

const keyExtractor = (item: HuDataMember) => `${item.id}`;

function DialogReactionList() {
  const {t} = useTranslation();
  const navigation = useNavigation();
  const tabsRef = useRef<TabsRef>(null);
  const [showContent, setShowContent] = useState(false);
  const {show, message, hideDialog, initialTab} = useReactionDialog();
  const reactions = useReactionList(message?.clientMsgId);

  const routes = useMemo(() => {
    if (!reactions) {
      return [];
    }

    const result: TabItem[] = [];
    for (const reaction of reactions) {
      // Filter tabs without reactions (count = 0)
      if (reaction.count > 0) {
        result.push({
          key: reaction.name,
          label: `${reaction.name} ${reaction.count}`,
        });
      }
    }

    return result;
  }, [reactions]);

  const initialIndex = useMemo(() => {
    return routes.findIndex(route => route.key === initialTab);
  }, [routes, initialTab]);

  const data = useMemo(() => {
    if (!reactions) {
      return {};
    }

    const sectionData = reactions.reduce((acc, reaction) => {
      acc[reaction.name] = reaction.users;
      return acc;
    }, {} as Record<string, HuDataMember[]>);

    return sectionData;
  }, [reactions]);
  const isTabsReady = routes.length > 0;

  const onAvatarPress = useCallback(
    (id: number) => () => {
      hideDialog();
      navigation.navigate(Screens.PROFILE, {
        userId: id,
      });
    },
    [navigation, hideDialog],
  );

  const renderItem = useCallback(
    ({item}: {item: HuDataMember}) => {
      const avatarProps = getUserAvatar(item, persistedUserId!);
      return (
        <ListItem
          title={avatarProps.title}
          avatar={avatarProps}
          onItemPress={onAvatarPress(item.id)}
          style={styles.item}
        />
      );
    },
    [onAvatarPress],
  );

  const renderScene = useCallback(
    ({route}: RenderSceneProps) => {
      const listData = data[route.key];
      return (
        <FlatList
          data={listData}
          keyExtractor={keyExtractor}
          renderItem={renderItem}
          bounces={false}
          showsVerticalScrollIndicator={false}
          getItemLayout={getItemLayout}
          contentContainerStyle={styles.list}
        />
      );
    },
    [data, renderItem],
  );

  const onClose = useCallback(() => {
    hideDialog();
  }, [hideDialog]);

  useBackHandler(() => {
    if (show) {
      hideDialog();
      return true;
    } else {
      return false;
    }
  });

  /**
   * Effect to show right away the dialog. This will render the tabs and the list asynchronously.
   * Right now the Tabs component has a bad performance when there are too many tabs(routes).
   */
  useEffect(() => {
    if (show && isTabsReady) {
      setTimeout(() => {
        setShowContent(true);
      }, 500);
    } else {
      setShowContent(false);
    }
  }, [show, isTabsReady]);

  return (
    <Dialog
      isVisible={show}
      onClose={onClose}
      title={t('chat.reactions')}
      snapPoints={snapPoints}
      contentStyle={styles.dialogContainer}
      enableContentPanningGesture={false}>
      <View style={styles.container}>
        {showContent ? (
          <Tabs
            ref={tabsRef}
            initialIndex={initialIndex}
            routes={routes}
            renderScene={renderScene}
            lazy
            swipeEnabled
          />
        ) : (
          <View style={styles.spinner}>
            <Spinner />
          </View>
        )}
      </View>
    </Dialog>
  );
}

export default memo(DialogReactionList);
