import { useTheme } from '@emotion/react';
import React from 'react';
import type { StyleProp, ViewProps, ViewStyle } from 'react-native';
import { FlatList, Platform, TouchableWithoutFeedback } from 'react-native';
import type { ItemType, TabType } from '..';
import Icon from '../../Icon';
import { isHeroIcon } from '../../Icon/utils';
import Typography from '../../Typography';
import {
  HeaderTabItem,
  HeaderTabItemIndicator,
  HeaderTabItemOutline,
  HeaderTabItemOutlineWrapper,
  HeaderTabItemWrapper,
  HeaderTabWrapper,
} from '../StyledScrollableTabs';
import TabWithBadge from '../TabWithBadge';
import useInitHighlightedAnimation from './hooks/useInitHighlightedAnimation';
import useInitUnderlinedAnimation from './hooks/useInitUnderlinedAnimation';

const getTabItem = ({
  item,
  color,
  active,
}: {
  item: ItemType;
  color: string;
  active: boolean;
}) => {
  if (isHeroIcon(item)) {
    return (
      <Icon
        icon={item}
        testID={`hero-icon-${item}`}
        size="small"
        style={{ color }}
      />
    );
  }

  if (typeof item === 'string') {
    return (
      <Typography.Body
        variant={active ? 'regular-bold' : 'regular'}
        numberOfLines={1}
        style={{ color }}
      >
        {item}
      </Typography.Body>
    );
  }

  return item({ color });
};

export interface ScrollableTabHeaderProps extends ViewProps {
  /**
   * Callback which is called on tab press, receiving key of upcoming active Tab.
   */
  onTabPress: (key: string) => void;
  /**
   * Current selected tab key.
   */
  selectedIndex?: number;
  /**
   * List of Tabs to be rendered. Each Tab must have an unique key.
   */
  tabs: TabType[];
  /**
   * Style for the tab navigation bar.
   */
  barStyle?: StyleProp<ViewStyle>;
  /**
   * Testing id of the component.
   */
  testID?: string;
  /**
   * component insets
   */
  insets?: {
    top: number;
    bottom: number;
    right: number;
    left: number;
  };
  /**
   * Variant of the tab header
   */
  variant?: 'underlined' | 'highlighted';
}
const ScrollableTabHeader = ({
  onTabPress,
  selectedIndex,
  tabs,
  barStyle,
  testID,
  insets = { top: 0, bottom: 0, right: 0, left: 0 },
  variant = 'highlighted',
}: ScrollableTabHeaderProps) => {
  const theme = useTheme();
  const flatListRef = React.useRef<FlatList>(null);

  // Init underlined animation data
  const { underlinedTranslateX, underlinedOpacity } =
    useInitUnderlinedAnimation({
      tabsLength: tabs.length,
      selectedIndex,
      variant,
    });

  // Init highlighted animation data
  const { tabsAnims } = useInitHighlightedAnimation({
    selectedIndex,
    tabsLength: tabs.length,
    variant,
  });

  React.useEffect(() => {
    const timeoutHandle: number | null = null;
    if (selectedIndex !== undefined && selectedIndex !== -1) {
      flatListRef.current?.scrollToIndex({
        index: selectedIndex,
        viewPosition: 0.5,
      });
    }

    return () => {
      if (timeoutHandle) {
        clearTimeout(timeoutHandle);
      }
    };
  }, [selectedIndex]);

  return (
    <HeaderTabWrapper themeInsets={insets} style={barStyle}>
      <FlatList<TabType>
        testID={testID}
        ref={flatListRef}
        horizontal
        data={tabs}
        keyExtractor={(tab) => String(tab.key)}
        showsHorizontalScrollIndicator={false}
        onScrollToIndexFailed={({ index }) => {
          setTimeout(
            () =>
              flatListRef.current?.scrollToIndex({
                index,
                viewPosition: 0.5,
              }),
            100
          );
        }}
        style={{
          borderBottomColor: theme.__hd__.tabs.colors.headerBottom,
          borderBottomWidth: theme.__hd__.tabs.sizes.indicator,
        }}
        contentContainerStyle={{
          paddingHorizontal: theme.__hd__.tabs.space.flatListHorizontalPadding,

          // Specify it here again or the indicator won't show
          ...(Platform.OS === 'android' && {
            borderBottomColor: theme.__hd__.tabs.colors.headerBottom,
            borderBottomWidth: theme.__hd__.tabs.sizes.indicator,
          }),
        }}
        renderItem={({ item: tab, index }) => {
          const {
            key,
            testID: tabItemTestID,
            activeItem,
            inactiveItem: originalInactiveItem,
            badge,
          } = tab;
          const active = selectedIndex === index;
          const activeAnimated = tabsAnims[index];
          const outlineScale = activeAnimated.interpolate({
            inputRange: [0, 1],
            outputRange: [0.5, 1],
          });

          const inactiveItem = originalInactiveItem ?? activeItem;
          const tabItem = getTabItem({
            item: active ? activeItem : inactiveItem,
            color: active
              ? theme.__hd__.tabs.colors.active
              : theme.__hd__.tabs.colors.inactive,
            active,
          });

          return (
            <TouchableWithoutFeedback
              key={key}
              onPress={() => {
                onTabPress(key);
              }}
              testID={tabItemTestID}
            >
              <HeaderTabItem isFirstItem={index === 0}>
                {variant === 'highlighted' && (
                  <HeaderTabItemOutlineWrapper>
                    <HeaderTabItemOutline
                      themeActive={active}
                      style={{
                        flex: 1,
                        transform: [
                          {
                            scaleX: outlineScale,
                          },
                        ],
                      }}
                    />
                  </HeaderTabItemOutlineWrapper>
                )}

                <HeaderTabItemWrapper>
                  <TabWithBadge config={badge} tabItem={tabItem} />
                </HeaderTabItemWrapper>

                {variant === 'underlined' && (
                  <HeaderTabItemIndicator
                    style={{
                      opacity: underlinedOpacity[index],
                      transform: [{ translateX: underlinedTranslateX[index] }],
                    }}
                  />
                )}
              </HeaderTabItem>
            </TouchableWithoutFeedback>
          );
        }}
      />
    </HeaderTabWrapper>
  );
};
export default ScrollableTabHeader;
