import React, {
  forwardRef,
  ReactNode,
  useCallback,
  useEffect,
  useImperativeHandle,
  useMemo,
  useRef,
  useState,
} from 'react';
import {StyleProp, View, ViewStyle} from 'react-native';
import {
  TabView as RNTabView,
  TabViewProps as RNTabViewProps,
} from 'react-native-tab-view';
import {useSharedValue} from 'react-native-reanimated';
import {WithCollapsible} from '@components/_core/WithCollapsible';
import {CollapsibleInfo} from '@interfaces/generic';
import {useTheme} from '@shared/theme';

import {AnimatedValueContext} from '../../hooks/useAnimatedValueContext';
import {useTabsChipsPager} from '../../hooks/useTabsChipsPager';
import {
  RenderSceneProps,
  TabItem,
  TabsHeaderProps,
  TabsRef,
} from '../../interfaces';
import {AnimatedTabsHeader} from '../AnimatedTabsHeader';
import {TabsChipsHeader} from './components/TabsChipsHeader';
import {styles} from './styles';
import {buildRenderSceneWithActive} from '../../utils';

interface Props {
  routes: TabItem[];
  initialIndex?: number;
  renderScene: (props: RenderSceneProps) => ReactNode;
  onTabChange?: (key: string, index: number) => void;
  showHeader?: boolean;
  renderLazyPlaceholder?: RNTabViewProps<TabItem>['renderLazyPlaceholder'];
  swipeEnabled?: boolean;
  usePager?: boolean;
  lazy?: boolean;
  collapsibleInfo?: CollapsibleInfo;
  style?: StyleProp<ViewStyle>;
  contentContainerStyle?: StyleProp<ViewStyle>;
  tabsBackgroundColor?: string;
}

export const TabsChips = forwardRef<TabsRef, Props>(
  (
    {
      routes,
      renderScene,
      onTabChange,
      renderLazyPlaceholder,
      swipeEnabled,
      usePager = true,
      lazy = true,
      initialIndex = 0,
      showHeader = true,
      collapsibleInfo,
      style,
      contentContainerStyle,
      tabsBackgroundColor,
    },
    ref,
  ) => {
    const {theme} = useTheme();
    const [index, setIndex] = useState<number>(initialIndex);
    const indexRef = useRef(initialIndex);
    const animatedValue = useSharedValue(0);
    const navigationState = useMemo(() => ({index, routes}), [index, routes]);

    useImperativeHandle(
      ref,
      () => ({
        goToIndex: newIndex => {
          indexRef.current = newIndex;
          setIndex(newIndex);
        },
        goToRouteKey: (newKey: string) => {
          const newIndex = routes.findIndex(route => route.key === newKey);
          indexRef.current = newIndex;
          setIndex(newIndex);
        },
        currentIndex: index,
      }),
      [index, routes],
    );

    const onIndexChange = useCallback(
      (indexValue: number): void => {
        indexRef.current = indexValue;
        setIndex(indexValue);
        onTabChange?.(routes[indexValue].key, indexValue);
      },
      [onTabChange, routes],
    );

    const {sceneProps, tabBarProps} = useTabsChipsPager({
      index,
      routes,
      onIndexChange,
    });

    const renderTabBar = useCallback(
      (props: TabsHeaderProps) => {
        const TabBar = (
          <AnimatedTabsHeader
            style={{
              backgroundColor:
                tabsBackgroundColor || theme.background.layout.tertiary,
            }}>
            <TabsChipsHeader
              {...props}
              style={style}
              contentContainerStyle={contentContainerStyle}
            />
          </AnimatedTabsHeader>
        );
        return showHeader ? (
          collapsibleInfo ? (
            <WithCollapsible collapsibleInfo={collapsibleInfo}>
              {TabBar}
            </WithCollapsible>
          ) : (
            TabBar
          )
        ) : null;
      },
      [
        showHeader,
        collapsibleInfo,
        style,
        contentContainerStyle,
        tabsBackgroundColor,
        theme.background.layout.tertiary,
      ],
    );

    const renderSceneWithActive = useMemo(
      () => buildRenderSceneWithActive(routes, indexRef, renderScene),
      [renderScene, routes],
    );

    /**
     * Effect to ensure show the tab header when changing tabs
     */
    useEffect(() => {
      animatedValue.value = 0;
    }, [animatedValue, index]);

    const animatedContextValue = useMemo(
      () => ({
        tabAnimatedValue: animatedValue,
        headerTranslateY: animatedValue,
      }),
      [animatedValue],
    );

    return (
      <AnimatedValueContext.Provider value={animatedContextValue}>
        {usePager ? (
          <RNTabView
            navigationState={navigationState}
            onIndexChange={onIndexChange}
            renderScene={renderSceneWithActive}
            renderTabBar={renderTabBar}
            renderLazyPlaceholder={renderLazyPlaceholder}
            swipeEnabled={swipeEnabled}
            lazy={lazy}
          />
        ) : (
          <View style={styles.contentContainer}>
            {renderTabBar(tabBarProps)}
            <View style={styles.contentContainer}>
              {renderSceneWithActive(sceneProps)}
            </View>
          </View>
        )}
      </AnimatedValueContext.Provider>
    );
  },
);
