import { BottomTabBarProps } from '@react-navigation/bottom-tabs';
import { CommonActions, Route } from '@react-navigation/native';
import React, { useCallback, useContext } from 'react';
import {
  Animated,
  Platform,
  StyleSheet,
  TouchableOpacity,
  useWindowDimensions,
  View,
} from 'react-native';
import { EdgeInsets, useSafeAreaInsets } from 'react-native-safe-area-context';
import { Colors, Radius, Styles } from '../../Consts';
import { Icon } from '../../Icon';
import { Text } from '../../Text';
import { FloatingButtonProps } from '../types';
import CustomBottomTabItem from './CustomBottomTabItem';
import { ApplicationContext, MiniAppContext } from '../../Context';

type Props = BottomTabBarProps & {
  activeTintColor?: string;
  inactiveTintColor?: string;
  floatingButton?: FloatingButtonProps;
  activeBackgroundColor?: string;
  allowFontScaling?: boolean;
  inactiveBackgroundColor?: string;
  labelStyle?: any;
  iconStyle?: any;
  showLabel?: boolean;
  style?: any;
  tabStyle?: any;
  badgeStyle?: any;
};

const getPaddingBottom = (insets: EdgeInsets) => {
  return Math.max(insets.bottom - Platform.select({ ios: 4, default: 0 }), 0);
};

export default function BottomTabBar({
  state,
  navigation,
  descriptors,
  activeBackgroundColor,
  activeTintColor,
  allowFontScaling,
  inactiveBackgroundColor,
  inactiveTintColor,
  labelStyle,
  iconStyle,
  showLabel,
  style,
  floatingButton,
}: Props) {
  const { theme } = useContext(ApplicationContext);
  const { routes } = state;
  const widthDevice = useWindowDimensions()?.width;
  const useFloating = floatingButton && state.routes.length % 2 === 0;
  const itemWidth = widthDevice / (state.routes.length + (useFloating ? 1 : 0));
  // const buildLink = useLinkBuilder();
  const indicatorAnimated = React.useRef(new Animated.Value(0)).current;
  const insets = useSafeAreaInsets();
  const paddingBottom = getPaddingBottom(insets);
  const focusedTab = state?.routes[state.index]?.name || routes[0]?.params;

  const context = useContext<any>(MiniAppContext);
  const showBaseLineDebug = context?.features?.showBaseLineDebug ?? false;

  /**
   * render tab item
   */
  const renderTabItem = useCallback(
    (data: Route<string, any>[]) => {
      return data?.map(route => {
        const focused = route?.params?.name === focusedTab;
        const { options } = descriptors[route.key];

        const onPress = () => {
          const event = navigation.emit({
            type: 'tabPress',
            target: route.key,
            canPreventDefault: true,
          });

          if (!focused && !event.defaultPrevented) {
            navigation.dispatch({
              ...CommonActions.navigate(route.name),
              target: state.key,
            });
          }
        };

        const onLongPress = () => {
          navigation.emit({
            type: 'tabLongPress',
            target: route.key,
          });
        };

        return (
          <CustomBottomTabItem
            key={route.key}
            route={route}
            label={options.tabBarLabel || options.title || route.name}
            focused={focused}
            onPress={onPress}
            onLongPress={onLongPress}
            activeTintColor={activeTintColor ?? theme.colors.primary}
            inactiveTintColor={inactiveTintColor ?? theme.colors.text.default}
            activeBackgroundColor={activeBackgroundColor}
            inactiveBackgroundColor={inactiveBackgroundColor}
            icon={options.tabBarIcon}
            badge={options.tabBarBadge}
            showLabel={showLabel}
            labelStyle={labelStyle}
            iconStyle={iconStyle}
            style={options.tabBarStyle}
            badgeStyle={options.tabBarBadgeStyle}
            allowFontScaling={allowFontScaling}
          />
        );
      });
    },
    [
      focusedTab,
      descriptors,
      activeTintColor,
      theme.colors.primary,
      theme.colors.text.default,
      inactiveTintColor,
      activeBackgroundColor,
      inactiveBackgroundColor,
      showLabel,
      labelStyle,
      iconStyle,
      allowFontScaling,
      navigation,
      state.key,
    ],
  );

  /**
   * render floating button
   */
  const renderFloatingButton = useCallback(() => {
    const renderFloatingIcon = () => {
      if (typeof floatingButton?.icon === 'string') {
        return <Icon source={floatingButton?.icon} size={32} color={'white'} />;
      }
      return floatingButton?.icon;
    };

    return (
      <View style={[Styles.flex, showBaseLineDebug && styles.debugBaseLine]}>
        <TouchableOpacity
          onPress={floatingButton?.onPress}
          style={styles.floatingContainer}
        >
          <View
            style={{
              ...styles.floatingContent,
              backgroundColor: activeTintColor ?? theme.colors.primary,
            }}
          >
            {renderFloatingIcon()}
          </View>
          <View
            style={{
              top: -4,
              backgroundColor: activeTintColor ?? theme.colors.primary,
              borderRadius: Radius.XL,
              paddingHorizontal: 6,
            }}
          >
            <Text
              numberOfLines={1}
              typography={'description_xs_regular'}
              color={'white'}
            >
              {floatingButton?.label}
            </Text>
          </View>
        </TouchableOpacity>
      </View>
    );
  }, [
    activeTintColor,
    floatingButton?.icon,
    floatingButton?.label,
    floatingButton?.onPress,
    showBaseLineDebug,
    theme.colors.primary,
  ]);

  /**
   * animated indicator
   */
  React.useEffect(() => {
    let index = state.index;
    if (useFloating && index > (state.routes.length - 1) / 2) {
      index += 1;
    }
    Animated.timing(indicatorAnimated, {
      toValue: itemWidth * index,
      useNativeDriver: true,
      duration: 200,
    }).start();
  }, [
    state.index,
    itemWidth,
    indicatorAnimated,
    useFloating,
    state.routes.length,
  ]);

  /**
   * render tab bar
   */
  const renderTabBar = () => {
    if (useFloating) {
      const middleIndex = routes.length / 2;
      const leftArr = routes.slice(0, middleIndex);
      const rightArr = routes.slice(middleIndex);
      return (
        <>
          {renderTabItem(leftArr)}
          {renderFloatingButton()}
          {renderTabItem(rightArr)}
        </>
      );
    }
    return renderTabItem(routes);
  };

  return (
    <Animated.View
      style={[
        floatingButton ? styles.tabBarFloatingButton : styles.tabBar,
        {
          backgroundColor: theme.colors.background.surface,
          borderTopColor: theme.colors.border.default,
        },
        {
          paddingBottom: paddingBottom,
          paddingHorizontal: Math.max(insets.left, insets.right),
        },
        style,
      ]}
      pointerEvents={'auto'}
    >
      <View style={styles.content} accessibilityLabel={'bottom_tab_bar'}>
        {useFloating && floatingButton?.container}
        <Animated.View
          style={{
            width: itemWidth,
            position: 'absolute',
            top: 0,
            transform: [{ translateX: indicatorAnimated }],
          }}
        >
          <View
            style={[
              styles.indicator,
              { backgroundColor: activeTintColor ?? theme.colors.primary },
            ]}
          />
        </Animated.View>
        {renderTabBar()}
      </View>
    </Animated.View>
  );
}

const styles = StyleSheet.create({
  content: {
    flex: 1,
    flexDirection: 'row',
  },
  tabBar: {
    left: 0,
    right: 0,
    bottom: 0,
    borderTopWidth: StyleSheet.hairlineWidth,
    elevation: 8,
  },
  tabBarFloatingButton: {
    left: 0,
    right: 0,
    bottom: 0,
    zIndex: 1,
    shadowColor: Colors.black_20,
    shadowOffset: { width: 0, height: -2 },
    shadowOpacity: 0.05,
    shadowRadius: 3,
    elevation: 8,
  },
  floatingContainer: {
    position: 'absolute',
    alignItems: 'center',
    left: 0,
    right: 0,
    top: -2,
    bottom: Platform.OS === 'ios' ? -6 : 4
  },
  floatingContent: {
    alignItems: 'center',
    justifyContent: 'center',
    height: 48,
    width: 48,
    borderRadius: 24,
    top: -10,
  },
  indicator: {
    height: 2,
    width: 44,
    alignSelf: 'center',
    borderBottomLeftRadius: 1,
    borderBottomRightRadius: 1,
  },
  debugBaseLine: { borderWidth: 1, borderColor: Colors.green_06 },
});
