import React, { useEffect, useRef, useState } from 'react';
import { EntranceAnimationDirection } from '../constants';
import { Styles } from '@cleartrip/ct-design-types';

export interface EntranceAnimationProps {
  direction: `${EntranceAnimationDirection}`;
  index?: number;
  children: React.ReactNode;
  staggerDelay?: number;
  maxStaggerIndex?: number;
  initialOffset?: number;
  duration?: number;
  containerStyle?: Styles;
  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 [shouldAnimate, setShouldAnimate] = useState(false);

  // Generate unique keyframe names based on direction and offset
  const keyframeName = `entrance-${direction.toLowerCase()}-${initialOffset}`;

  useEffect(() => {
    if (!hasAnimated.current && startAnimation) {
      hasAnimated.current = true;

      // Start animation after stagger delay
      const timer = setTimeout(() => {
        setShouldAnimate(true);

        // Call onAnimationComplete after animation finishes
        const animationCompleteTimer = setTimeout(
          () => {
            onAnimationComplete();
          },
          duration + (opacityAnimation ? duration * 0.5 : 0),
        );

        return () => clearTimeout(animationCompleteTimer);
      }, wrappedIndex * staggerDelay);

      return () => clearTimeout(timer);
    }
  }, [wrappedIndex, staggerDelay, duration, direction, startAnimation, onAnimationComplete, opacityAnimation]);

  // Create dynamic styles including keyframes
  const dynamicStyles = React.useMemo(() => {
    const keyframes =
      direction === EntranceAnimationDirection.B2T
        ? `
        @keyframes ${keyframeName} {
          from {
            transform: translateY(${initialOffset}px);
          }
          to {
            transform: translateY(0);
          }
        }
      `
        : `
        @keyframes ${keyframeName} {
          from {
            transform: translateX(-${initialOffset}px);
          }
          to {
            transform: translateX(0);
          }
        }
      `;

    const opacityKeyframes = opacityAnimation
      ? `
      @keyframes ${keyframeName}-opacity {
        from {
          opacity: 0.5;
        }
        to {
          opacity: 1;
        }
      }
    `
      : '';

    return `
      <style>
        ${keyframes}
        ${opacityKeyframes}
      </style>
    `;
  }, [direction, initialOffset, keyframeName, opacityAnimation]);

  const animationStyle = {
    ...(fillContainer && { flex: 1 }),
    ...containerStyle,
    ...(shouldAnimate && {
      animation: `${keyframeName} ${duration}ms ease-out forwards${opacityAnimation ? `, ${keyframeName}-opacity ${duration * 0.5}ms ease-out ${duration}ms forwards` : ''}`,
    }),
    ...(opacityAnimation && !shouldAnimate && { opacity: 0.5 }),
    ...(direction === EntranceAnimationDirection.B2T &&
      !shouldAnimate && {
        transform: `translateY(${initialOffset}px)`,
      }),
    ...(direction === EntranceAnimationDirection.L2R &&
      !shouldAnimate && {
        transform: `translateX(-${initialOffset}px)`,
      }),
  };

  return (
    <>
      <div dangerouslySetInnerHTML={{ __html: dynamicStyles }} />
      <div style={animationStyle as React.CSSProperties}>{children}</div>
    </>
  );
};

export default EntranceAnimation;
