import React, {useState, useEffect, useRef} from 'react';
import {
  View,
  TouchableOpacity,
  Text,
  StyleSheet,
  Dimensions,
} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Svg, {Path, Circle, Text as SvgText} from 'react-native-svg';
import Animated, {
  useSharedValue,
  useAnimatedProps,
  useAnimatedStyle,
  withTiming,
  withRepeat,
  withSequence,
  Easing,
  runOnJS,
} from 'react-native-reanimated';
import type {CurvedTabBarProps} from '../types';
import {Platform} from 'react-native';

// Try to import Haptics for native platforms, but handle web gracefully
let Haptics: any = null;
if (Platform.OS !== 'web') {
  try {
    // Dynamic import for Expo Haptics - only works on native platforms
    Haptics = require('expo-haptics');
  } catch (e) {
    console.warn(
      'expo-haptics is not available, haptic feedback will be disabled'
    );
  }
}

const {width} = Dimensions.get('window');

// Create animated version of the SVG Path
const AnimatedPath = Animated.createAnimatedComponent(Path);

const CurvedTabBar: React.FC<CurvedTabBarProps> = ({
  state,
  descriptors,
  navigation,
  backgroundColor = '#FFFFFF',
  strokeColor = 'rgba(0,0,0,0.05)',
  strokeWidth = 0.5,
  tabBarHeight = 80,
  showFAB = true,
  fabSize = 60,
  fabColor = '#00C09A',
  fabIcon,
  onFabPress,
  curveHeight: initialCurveHeight = 14,
  debug = false,
  fabTabIndex = 2,
  style,
  fabStyle,
  animateOnMount = true,
}) => {
  const insets = useSafeAreaInsets();
  const [showDebug, setShowDebug] = useState(debug);
  const [fabVisible, setFabVisible] = useState(!animateOnMount);

  // Ref to track if initial animation has run
  const initialAnimationCompleted = useRef(false);

  const TAB_BAR_HEIGHT = tabBarHeight;
  const FAB_SIZE = fabSize;

  const tabBarStyle = {
    height: TAB_BAR_HEIGHT + insets.bottom,
    paddingBottom: insets.bottom,
  };

  // SVG viewBox parameters
  const viewBoxWidth = 100;
  const viewBoxHeight = 34;

  // Calculate dimensions for better positioning of the FAB
  const fabTopOffset = 20;
  const leftControlXStart = 42;
  const rightControlXStart = 58;

  // Animated shared values for the curve
  const curveStartLeft = useSharedValue(30);
  const curveStartRight = useSharedValue(70);
  const curveHeight = useSharedValue(0); // Start flat
  const curveMidpointY = useSharedValue(0); // Start flat
  const leftControlX = useSharedValue(leftControlXStart);
  const rightControlX = useSharedValue(rightControlXStart);
  const fabScale = useSharedValue(0); // Start at 0 (invisible)
  const fabOpacity = useSharedValue(0); // Start fully transparent

  // Function to handle animation completion
  const onCurveAnimationComplete = () => {
    setFabVisible(true);
  };

  // Initial animation on component mount - only runs once
  useEffect(() => {
    if (initialAnimationCompleted.current || !animateOnMount) return;

    // Start the animation after a short delay
    setTimeout(() => {
      curveHeight.value = withTiming(
        initialCurveHeight,
        {
          duration: 800,
          easing: Easing.elastic(1.5),
        },
        (finished) => {
          if (finished) {
            // When curve animation finishes, mark as complete and reveal the FAB
            initialAnimationCompleted.current = true;
            runOnJS(onCurveAnimationComplete)();
          }
        }
      );

      curveMidpointY.value = withTiming(initialCurveHeight, {
        duration: 800,
        easing: Easing.elastic(1.5),
      });
    }, 300);
  }, [animateOnMount, initialCurveHeight, curveHeight, curveMidpointY]); // Include all dependencies

  // Handle fab animation separately - only runs when fabVisible changes to true
  useEffect(() => {
    if (fabVisible && initialAnimationCompleted.current) {
      // Animate the FAB in
      fabOpacity.value = withTiming(1, {duration: 200});
      fabScale.value = withSequence(
        withTiming(1.2, {duration: 300, easing: Easing.out(Easing.cubic)}),
        withTiming(1, {duration: 200, easing: Easing.elastic(3)})
      );

      // After FAB appears, start the subtle breathing animation
      setTimeout(() => {
        fabScale.value = withRepeat(
          withSequence(
            withTiming(1.05, {
              duration: 1500,
              easing: Easing.inOut(Easing.sin),
            }),
            withTiming(1, {duration: 1500, easing: Easing.inOut(Easing.sin)})
          ),
          -1, // Infinite repeat
          true // Reverse
        );
      }, 800);
    }
  }, [fabVisible, fabOpacity, fabScale]); // Include animated values in dependencies

  // Tab selection animation
  useEffect(() => {
    const currentIndex = state.index;
    // Skip animation if fabTabIndex is hidden or selected tab is the FAB
    if (currentIndex === fabTabIndex) return;

    if (currentIndex < fabTabIndex) {
      // Left side tabs selected, shift curve slightly left
      leftControlX.value = withTiming(leftControlXStart - currentIndex * 3, {
        duration: 300,
      });
      rightControlX.value = withTiming(rightControlXStart - currentIndex * 2, {
        duration: 300,
      });
    } else if (currentIndex > fabTabIndex) {
      // Right side tabs selected, shift curve slightly right
      const adjustedIndex =
        currentIndex > fabTabIndex ? currentIndex - 1 : currentIndex;
      leftControlX.value = withTiming(
        leftControlXStart + (adjustedIndex - fabTabIndex) * 2,
        {duration: 300}
      );
      rightControlX.value = withTiming(
        rightControlXStart + (adjustedIndex - fabTabIndex) * 3,
        {duration: 300}
      );
    }
  }, [
    state.index,
    fabTabIndex,
    leftControlXStart,
    rightControlXStart,
    leftControlX,
    rightControlX,
  ]);

  // Define points for debugging (in viewBox coordinate space)
  const debugPoints = [
    {x: 0, y: 0, label: 'M0,0', color: '#FF3333'},
    {x: 0, y: viewBoxHeight, label: `L0,${viewBoxHeight}`, color: '#FF9900'},
    {
      x: viewBoxWidth,
      y: viewBoxHeight,
      label: `L100,${viewBoxHeight}`,
      color: '#FF9900',
    },
    {x: viewBoxWidth, y: 0, label: 'L100,0', color: '#FF9900'},

    // Control points for first curve section
    {x: 100, y: 0, label: 'C100,0', color: '#33CC33'},
    {
      x: curveStartRight.value,
      y: 0,
      label: `${curveStartRight.value},0`,
      color: '#33CC33',
    },
    {
      x: curveStartRight.value,
      y: 0,
      label: `${curveStartRight.value},0`,
      color: '#33CC33',
    },

    // Control points for second curve section (these are animated)
    {
      x: rightControlX.value,
      y: 0,
      label: `C${rightControlX.value},0`,
      color: '#FF33CC',
    },
    {
      x: rightControlX.value,
      y: curveHeight.value,
      label: `${rightControlX.value},${curveHeight.value}`,
      color: '#FF33CC',
    },
    {
      x: 50,
      y: curveMidpointY.value,
      label: `50,${curveMidpointY.value}`,
      color: '#FF33CC',
    },

    // Control points for third curve section (these are animated)
    {
      x: leftControlX.value,
      y: curveHeight.value,
      label: `C${leftControlX.value},${curveHeight.value}`,
      color: '#9933CC',
    },
    {
      x: leftControlX.value,
      y: 0,
      label: `${leftControlX.value},0`,
      color: '#9933CC',
    },
    {
      x: curveStartLeft.value,
      y: 0,
      label: `${curveStartLeft.value},0`,
      color: '#9933CC',
    },

    // Control points for final curve section
    {
      x: curveStartLeft.value,
      y: 0,
      label: `C${curveStartLeft.value},0`,
      color: '#3366FF',
    },
    {x: 0, y: 0, label: '0,0', color: '#3366FF'},
    {x: 0, y: 0, label: '0,0', color: '#3366FF'},
  ];

  // Create animated props for the path
  const animatedPathProps = useAnimatedProps(() => {
    const path = `
      M0,0 
      L0,${viewBoxHeight} 
      L${viewBoxWidth},${viewBoxHeight} 
      L${viewBoxWidth},0 
      C${viewBoxWidth},0 ${curveStartRight.value},0 ${curveStartRight.value},0 
      C${rightControlX.value},0 ${rightControlX.value},${curveHeight.value} 50,${curveMidpointY.value} 
      C${leftControlX.value},${curveHeight.value} ${leftControlX.value},0 ${curveStartLeft.value},0 
      C${curveStartLeft.value},0 0,0 0,0 Z
    `;

    return {
      d: path,
    };
  });

  // Animated props for the FAB
  const animatedFabStyle = useAnimatedStyle(() => {
    return {
      opacity: fabOpacity.value,
      transform: [
        {scale: fabScale.value},
        {translateY: withTiming(fabOpacity.value * 0, {duration: 300})}, // Small bounce up effect
      ],
    };
  });

  // Function to handle FAB press with animation
  const handleFabPress = () => {
    // Trigger haptic feedback on native platforms
    if (Platform.OS !== 'web' && Haptics) {
      Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
    }

    // Create a pulse animation on the curve
    const pulse = () => {
      curveHeight.value = withSequence(
        withTiming(curveHeight.value + 4, {
          duration: 150,
          easing: Easing.inOut(Easing.quad),
        }),
        withTiming(initialCurveHeight, {
          duration: 300,
          easing: Easing.elastic(2),
        })
      );

      curveMidpointY.value = withSequence(
        withTiming(curveMidpointY.value + 4, {
          duration: 150,
          easing: Easing.inOut(Easing.quad),
        }),
        withTiming(initialCurveHeight, {
          duration: 300,
          easing: Easing.elastic(2),
        })
      );
    };

    // Create a squeeze animation
    const squeeze = () => {
      curveStartLeft.value = withSequence(
        withTiming(curveStartLeft.value + 3, {duration: 200}),
        withTiming(30, {
          duration: 300,
          easing: Easing.bezier(0.34, 1.56, 0.64, 1),
        })
      );

      curveStartRight.value = withSequence(
        withTiming(curveStartRight.value - 3, {duration: 200}),
        withTiming(70, {
          duration: 300,
          easing: Easing.bezier(0.34, 1.56, 0.64, 1),
        })
      );
    };

    // Run both animations
    pulse();
    squeeze();

    // Add a pop animation for the FAB button
    fabScale.value = withSequence(
      withTiming(1.2, {duration: 150, easing: Easing.inOut(Easing.quad)}),
      withTiming(1, {duration: 300, easing: Easing.elastic(4)})
    );

    // Call the custom onFabPress function if provided
    if (onFabPress) {
      onFabPress();
    }
  };

  // Toggle debug mode
  const toggleDebug = () => {
    setShowDebug(!showDebug);
  };

  // Long press on FAB to enable debug mode
  const handleLongPress = () => {
    setShowDebug(!showDebug);
  };

  return (
    <View style={[styles.container, tabBarStyle, style]}>
      {/* SVG Tab Bar Background with Curve */}
      <View style={styles.tabBarContainer}>
        <Svg
          width={width}
          height={TAB_BAR_HEIGHT}
          viewBox={`0 0 ${viewBoxWidth} ${viewBoxHeight}`}
          preserveAspectRatio="none"
          style={styles.tabBarBackground}
        >
          <AnimatedPath
            animatedProps={animatedPathProps}
            fill={backgroundColor}
            stroke={strokeColor}
            strokeWidth={strokeWidth}
          />

          {/* Debug Points - Only shown when debug mode is enabled */}
          {showDebug &&
            debugPoints.map((point, index) => (
              <React.Fragment key={index}>
                <Circle
                  cx={typeof point.x === 'number' ? point.x : point.x}
                  cy={typeof point.y === 'number' ? point.y : point.y}
                  r={1}
                  fill={point.color}
                  stroke="#000"
                  strokeWidth={0.2}
                />
                <SvgText
                  x={typeof point.x === 'number' ? point.x : point.x}
                  y={(typeof point.y === 'number' ? point.y : point.y) - 1.5}
                  fill={point.color}
                  stroke="#FFF"
                  strokeWidth={0.1}
                  fontSize="1.8"
                  textAnchor="middle"
                >
                  {point.label}
                </SvgText>
              </React.Fragment>
            ))}
        </Svg>
      </View>

      {/* Debug toggle button */}
      {showDebug && (
        <TouchableOpacity style={styles.debugButton} onPress={toggleDebug}>
          <Text style={styles.debugButtonText}>Hide Debug</Text>
        </TouchableOpacity>
      )}

      {/* FAB button - positioned to overlap with the curve */}
      {showFAB && (
        <Animated.View
          style={[
            styles.fabContainer,
            {bottom: TAB_BAR_HEIGHT - fabTopOffset},
            animatedFabStyle,
            fabStyle,
          ]}
        >
          <TouchableOpacity
            onPress={handleFabPress}
            onLongPress={handleLongPress}
            activeOpacity={0.8}
          >
            <View
              style={[
                styles.fab,
                {
                  width: FAB_SIZE,
                  height: FAB_SIZE,
                  borderRadius: FAB_SIZE / 2,
                  backgroundColor: fabColor,
                },
              ]}
            >
              {fabIcon}
            </View>
          </TouchableOpacity>
        </Animated.View>
      )}

      {/* Tab bar content */}
      <View style={styles.tabBar}>
        {state.routes.map((route, index) => {
          const descriptor = descriptors[route.key];
          if (!descriptor) return null;

          const {options} = descriptor;
          const label = options.title || route.name;
          const isFocused = state.index === index;

          // Skip FAB position if showFAB is true
          if (showFAB && index === fabTabIndex) {
            return <View key={route.key} style={styles.emptyTab} />;
          }

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

            if (!isFocused && !event.defaultPrevented) {
              navigation.navigate(route.name);
            }
          };

          // Adjust spacing for tabs to account for the center FAB
          const tabPositionStyle = showFAB
            ? {
                // If after FAB tab (index > fabTabIndex), add extra space to account for FAB
                marginLeft: index > fabTabIndex ? 10 : 0,
                marginRight: index < fabTabIndex ? 10 : 0,
              }
            : {};

          return (
            <TouchableOpacity
              key={route.key}
              accessibilityRole="button"
              accessibilityState={isFocused ? {selected: true} : {}}
              accessibilityLabel={options.tabBarAccessibilityLabel as any}
              testID={(options as any).tabBarTestID}
              onPress={onPress}
              style={[styles.tabItem, tabPositionStyle]}
            >
              {options.tabBarIcon &&
                options.tabBarIcon({
                  focused: isFocused,
                  color: isFocused ? '#000' : '#999',
                  size: 24,
                })}
              <Text
                style={[
                  styles.tabLabel,
                  isFocused ? styles.tabLabelFocused : styles.tabLabelInactive,
                ]}
                numberOfLines={1}
              >
                {label}
              </Text>
            </TouchableOpacity>
          );
        })}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
    backgroundColor: 'transparent',
  },
  tabBarContainer: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
  },
  tabBarBackground: {
    position: 'absolute',
    bottom: 0,
  },
  fabContainer: {
    position: 'absolute',
    alignSelf: 'center',
    zIndex: 10,
  },
  fab: {
    justifyContent: 'center',
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 3,
    },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 8,
    flexDirection: 'row',
    gap: 8,
  },
  tabBar: {
    flexDirection: 'row',
    justifyContent: 'space-around',
    alignItems: 'flex-end',
    height: 80,
  },
  tabItem: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'flex-end',
    marginBottom: 10,
  },
  emptyTab: {
    flex: 1,
  },
  tabLabel: {
    fontSize: 12,
    marginTop: 2,
    textAlign: 'center',
  },
  tabLabelFocused: {
    color: '#000',
  },
  tabLabelInactive: {
    color: '#999',
  },
  debugButton: {
    position: 'absolute',
    top: 5,
    right: 10,
    backgroundColor: 'rgba(0,0,0,0.5)',
    paddingHorizontal: 8,
    paddingVertical: 4,
    borderRadius: 4,
    zIndex: 999,
  },
  debugButtonText: {
    color: 'white',
    fontSize: 10,
  },
});

export default CurvedTabBar;
