import React, {useCallback, useMemo, useRef} from 'react';
import {FlatList, ListRenderItem, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useFocusEffect} from '@react-navigation/native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {Spinner, Typography, RefreshControl} from '@components';
import {Navigation} from '@interfaces/navigation';
import {ExternalServiceProviderDTO} from '@modules/widgets/interfaces';
import {useShowCallStatusBar} from '@modules/calls/store/selectors';
import {
  useGetAppModules,
  useGetWidgets,
  useGetIDPProviders,
} from '@modules/widgets/hooks';
import {Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {fetchModulesNotifications, APPS_TAB_MODULES} from '@shared/utils';
import {useCommunityFeature} from '@stores/communityFeatures';

import WidgetCard, {WidgetCardProps} from './components/WidgetCard';
import {getContainerStyle, getTitleStyle, styles} from './styles';

type WidgetData = Nullable<WidgetCardProps & {id: string | number}>;

const keyExtractor = (_: WidgetData, index: number) => `${index}`;

const renderItem: ListRenderItem<WidgetData> = ({item}) =>
  item ? <WidgetCard {...item} /> : <View style={styles.emptyWidget} />;

function Widgets({navigation}: Navigation<Screens.WIDGETS>) {
  const {theme} = useTheme();
  const {t} = useTranslation();
  const {top} = useSafeAreaInsets();
  const showCallStatusBar = useShowCallStatusBar();
  const appModules = useGetAppModules();
  const deferRedBubbles = useCommunityFeature('DEFER_RED_BUBBLES');
  const containerStyle = useMemo(
    () =>
      getContainerStyle(
        showCallStatusBar,
        top,
        theme.background.layout.default,
      ),
    [showCallStatusBar, theme.background.layout.default, top],
  );
  const titleStyle = useMemo(
    () => getTitleStyle(showCallStatusBar),
    [showCallStatusBar],
  );

  const hasFetchedDeferred = useRef(false);

  useFocusEffect(
    useCallback(() => {
      if (!hasFetchedDeferred.current && deferRedBubbles) {
        fetchModulesNotifications(APPS_TAB_MODULES);
        hasFetchedDeferred.current = true;
      }
    }, [deferRedBubbles]),
  );
  const {
    widgets,
    refreshList: refreshWidgets,
    isRefreshing: isWidgetsRefreshing,
  } = useGetWidgets();
  const {idpProviders, isIDPLoading, getIDPNextPage, isFetchingIDPNextPage} =
    useGetIDPProviders();
  const showWidgets = !isIDPLoading && !isFetchingIDPNextPage;

  const goToIDP = useCallback(
    (provider: ExternalServiceProviderDTO) => () => {
      if (
        provider.protocol === 'OAUTH' &&
        provider.clientId &&
        provider.audienceIdentifier &&
        provider.redirectUri
      ) {
        navigation.navigate(Screens.IDP, {
          id: provider.id,
          oauth: {
            clientId: provider.clientId,
            audienceIdentifier: provider.audienceIdentifier,
            redirectUri: provider.redirectUri,
          },
        });
      } else {
        navigation.navigate(Screens.IDP, {id: provider.id});
      }
    },
    [navigation],
  );

  const onRefreshScreen = useCallback(() => {
    showWidgets && refreshWidgets();
  }, [refreshWidgets, showWidgets]);

  const data: WidgetData[] = useMemo(() => {
    let widgetList: WidgetData[] = [
      ...appModules.map(appModule => ({
        id: appModule.id,
        label: appModule.label,
        logo: appModule.logo || appModule.icon,
        Svg: appModule.Svg,
        svgProps: appModule.svgProps,
        unreadMessages: appModule.badges,
        onPress: appModule.onPress,
        isNew: appModule.isNew,
      })),
      ...idpProviders.map(provider => ({
        id: provider.id,
        label: provider.name,
        logo: {uri: provider.appIcon},
        onPress: goToIDP(provider),
      })),
    ];

    // Add community widgets when all the libraries are listed
    if (showWidgets) {
      widgetList = [
        ...widgetList,
        ...widgets.map(widget => ({
          id: widget.id,
          label: widget.title,
          logo: widget.icon,
          onPress: widget.onPress,
        })),
      ];
    }

    const whiteSpaces = widgetList.length % 3;

    if (whiteSpaces === 2) {
      widgetList.push(null);
    } else if (whiteSpaces === 1) {
      widgetList.push(null, null);
    }

    return widgetList;
  }, [appModules, idpProviders, showWidgets, goToIDP, widgets]);

  return (
    <View style={[styles.container, containerStyle]}>
      <FlatList
        testID="apps-flatlist"
        data={data}
        renderItem={renderItem}
        keyExtractor={keyExtractor}
        onEndReached={getIDPNextPage}
        ListHeaderComponent={
          <Typography variant="xl" weight="semiBold" style={titleStyle}>
            {t('widgets.apps')}
          </Typography>
        }
        ListFooterComponent={
          isFetchingIDPNextPage ? (
            <View style={styles.loadingContainer}>
              <Spinner />
            </View>
          ) : null
        }
        numColumns={3}
        contentContainerStyle={styles.listContainer}
        columnWrapperStyle={styles.columnWrapper}
        refreshControl={
          <RefreshControl
            onRefresh={onRefreshScreen}
            refreshing={isWidgetsRefreshing}
          />
        }
        showsVerticalScrollIndicator={false}
      />
    </View>
  );
}

export default Widgets;
