import React, { useEffect, useRef } from 'react';

import Animated, { Easing, useAnimatedStyle, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';

import { EntranceAnimationDirection } from '../constants';
import { ViewStyle } from 'react-native';

export interface EntranceAnimationProps {
  direction: `${EntranceAnimationDirection}`;
  index?: number;
  children: React.ReactNode;
  staggerDelay?: number;
  maxStaggerIndex?: number;
  initialOffset?: number;
  duration?: number;
  containerStyle?: ViewStyle;
  fillContainer?: boolean;
  opacityAnimation?: boolean;
  startAnimation?: boolean;
  onAnimationComplete?: () => void;
}

const EntranceAnimation: React.FC<EntranceAnimationProps> = ({
  direction,
  index = 0,
  children,
  staggerDelay = 80,
  maxStaggerIndex = 5,
  initialOffset = 200,
  duration = 200,
  containerStyle,
  fillContainer = false,
  opacityAnimation = true,
  startAnimation = true,
  onAnimationComplete = () => void 0,
}) => {
  // Wrap index for staggered effect
  const wrappedIndex = index % (maxStaggerIndex + 1);

  // Track if animation has already been executed
  const hasAnimated = useRef(false);

  const translate = useSharedValue(initialOffset);
  const opacity = useSharedValue(opacityAnimation ? 0 : 1);

  // Callback to emit animation complete event
  useEffect(() => {
    if (!hasAnimated.current && startAnimation) {
      hasAnimated.current = true;
      translate.value = withDelay(
        wrappedIndex * staggerDelay,
        withTiming(0, { duration, easing: Easing.inOut(Easing.ease) }),
      );
      opacity.value = withDelay(
        wrappedIndex * staggerDelay,
        withTiming(1, { duration: duration * 0.2, easing: Easing.inOut(Easing.ease) }),
      );

      // Emit animation complete event after animation duration
      const totalDelay = wrappedIndex * staggerDelay + duration + duration * 0.5;
      setTimeout(() => {
        onAnimationComplete();
      }, totalDelay);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [wrappedIndex, staggerDelay, duration, direction, startAnimation, onAnimationComplete]);

  const animatedStyle = useAnimatedStyle(() => {
    const transform =
      direction === EntranceAnimationDirection.B2T
        ? [{ translateY: translate.value }]
        : [{ translateX: translate.value }];

    const baseStyle = {
      transform: transform,
      opacity: opacity.value,
    };

    // Add flex: 1 if fillContainer is true
    const layoutStyle = fillContainer ? { flex: 1 } : {};

    return {
      ...baseStyle,
      ...layoutStyle,
      ...containerStyle,
    };
  });

  return <Animated.View style={animatedStyle}>{children}</Animated.View>;
};

export default EntranceAnimation;
