/* eslint-disable react-native/no-unused-styles */
import React, { useCallback, useMemo, useRef } from "react";
import { FlatList, View, ImageBackground } from "react-native";
import * as R from "ramda";
import { useConfiguration } from "@applicaster/zapp-react-native-utils/reactHooks/configuration";
import { noop } from "@applicaster/zapp-react-native-utils/functionUtils";
import { isEmptyOrNil } from "@applicaster/zapp-react-native-utils/cellUtils";
import { focusManager } from "@applicaster/zapp-react-native-utils/appUtils/focusManager";
import { FocusableGroup } from "@applicaster/zapp-react-native-ui-components/Components/FocusableGroup";
import { Focusable } from "@applicaster/zapp-react-native-ui-components/Components/Focusable";
import { useAccessibilityManager } from "@applicaster/zapp-react-native-utils/appUtils/accessibilityManager/hooks";
import { Gutter } from "../Gutter";
import Tab from "./Tab";
import { getStyles } from "./styles";
import {
  getId,
  scrollToSelectedIndex as scrollToSelectedIndexFn,
  generateFocusableId,
  applyFontConfig,
} from "./utils";

const VIEW_POSITION = 0.5;

const TabsComponent = ({
  entry,
  groupId,
  id,
  parentFocus,
  style,
  selectedEntryIndex,
  setSelectedEntry,
  accessibility,
}: TabsProps & Partial<TabsSelectionContextType>) => {
  const configuration = useConfiguration();
  const config = applyFontConfig(configuration);
  const styles = useMemo(() => getStyles(config), [config]);

  const accessibilityManager = useAccessibilityManager({});

  const {
    tab_bar_gutter: horizontalGutter,
    tab_bar_background_image: bgImage,
    component_padding_left: componentPaddingLeft,
    component_padding_right: componentPaddingRight,
    tab_bar_item_width: itemWidth,
  } = config;

  const {
    tabs,
    tabsWrapper,
    tabsBackground,
    tabsListWrapper,
    tabsListContentContainer,
  } = styles;

  const flatListRef = useRef<FlatList>(null);
  const selectedItem = useRef<string | null>(null);

  const entryLength = R.length(entry);

  const scrollToSelectedIndex = useMemo(
    () => scrollToSelectedIndexFn(flatListRef, config, entryLength),
    [config]
  );

  const onListElementFocus = useCallback(
    (index, isSelected: boolean, item: ZappEntry) => {
      if (isSelected) {
        accessibilityManager.readText({
          text: `${accessibility?.selectedHint} ${item.title}`,
        });
      } else {
        accessibilityManager.readText({
          text: `${accessibility?.hint} ${item.title}`,
        });
      }

      scrollToSelectedIndex(index, VIEW_POSITION);
    },
    [scrollToSelectedIndex, accessibility]
  );

  const renderItem = useCallback(
    ({ item, index }) => {
      const itemId = generateFocusableId(getId(item));

      const isSelected = R.equals(index, selectedEntryIndex);

      const focusableId = `${id}-${itemId}`;

      if (isSelected && selectedItem?.current !== focusableId) {
        selectedItem.current = focusableId;
      }

      const isLast = R.equals(index, entryLength - 1);
      const isFirst = R.equals(index, 0);

      const style = {
        paddingLeft: isFirst ? Number(componentPaddingLeft) : 0,
        paddingRight: isLast ? Number(componentPaddingRight) : 0,
        marginLeft: isFirst ? -Number(componentPaddingLeft) : 0,
        marginRight: isLast ? -Number(componentPaddingRight) : 0,
      };

      return (
        <Focusable
          groupId={id}
          id={itemId}
          testID={itemId}
          preferredFocus={isSelected}
          onFocus={() => onListElementFocus(index, isSelected, item)}
          onPress={() => setSelectedEntry && setSelectedEntry(item)}
          style={style}
        >
          {(focused) => (
            <Tab
              id={itemId}
              item={item}
              focused={focused}
              selected={isSelected}
              styles={styles}
              config={config}
            />
          )}
        </Focusable>
      );
    },
    [onListElementFocus, id, selectedEntryIndex]
  );

  const renderGutter = useCallback(
    () => <Gutter width={horizontalGutter} />,
    [horizontalGutter]
  );

  const onLayoutChange = useCallback(() => {
    scrollToSelectedIndex(selectedEntryIndex, VIEW_POSITION);
  }, [scrollToSelectedIndex, selectedEntryIndex]);

  const getItemLayout = useCallback(
    (_data, index) => ({
      length: itemWidth,
      offset: (itemWidth + (horizontalGutter || 0)) * index,
      index,
    }),
    [itemWidth, horizontalGutter]
  );

  React.useEffect(() => {
    const currentFocusElement = focusManager.getCurrentFocus();

    if (!currentFocusElement && selectedItem.current) {
      focusManager.setFocus(selectedItem.current);
    }
  }, []);

  return (
    <View style={[tabsWrapper, style]}>
      <FocusableGroup
        groupId={groupId}
        id={id}
        preferredFocus
        shouldUsePreferredFocus
        isWithMemory={false}
        nextFocusDown={parentFocus?.nextFocusDown}
        onFocus={() => {
          accessibilityManager.addHeading(accessibility?.announcement);
        }}
      >
        <View style={tabs}>
          <ImageBackground
            style={tabsBackground}
            source={{ uri: !isEmptyOrNil(bgImage) ? bgImage : undefined }}
          >
            <FlatList
              horizontal
              onLayout={onLayoutChange}
              contentContainerStyle={tabsListContentContainer}
              scrollEnabled={false}
              showsVerticalScrollIndicator={false}
              showsHorizontalScrollIndicator={false}
              ref={flatListRef}
              onScrollToIndexFailed={noop}
              keyExtractor={getId}
              initialScrollIndex={selectedEntryIndex}
              extraData={selectedEntryIndex}
              data={entry}
              renderItem={renderItem}
              ItemSeparatorComponent={renderGutter}
              getItemLayout={getItemLayout}
              style={tabsListWrapper}
              initialNumToRender={entryLength}
              maxToRenderPerBatch={entryLength}
              removeClippedSubviews={false}
            />
          </ImageBackground>
        </View>
      </FocusableGroup>
    </View>
  );
};

export const Tabs = React.memo(TabsComponent);
