import React from 'react';
import { motion, useInView } from 'framer-motion';

export interface ScrollRevealProps {
  /** Children to animate */
  children: React.ReactNode;
  /** Animation variant */
  variant?: 'fadeIn' | 'fadeUp' | 'fadeDown' | 'fadeLeft' | 'fadeRight' | 'scaleUp' | 'scaleDown';
  /** Duration of animation in seconds */
  duration?: number;
  /** Delay before animation starts in seconds */
  delay?: number;
  /** Only animate once (default: true) */
  once?: boolean;
  /** Amount of element that must be visible to trigger (0-1) */
  amount?: number;
  /** Additional CSS classes */
  className?: string;
  /** Disable animation (renders children directly) */
  disabled?: boolean;
}

const variants = {
  fadeIn: {
    hidden: { opacity: 0 },
    visible: { opacity: 1 },
  },
  fadeUp: {
    hidden: { opacity: 0, y: 40 },
    visible: { opacity: 1, y: 0 },
  },
  fadeDown: {
    hidden: { opacity: 0, y: -40 },
    visible: { opacity: 1, y: 0 },
  },
  fadeLeft: {
    hidden: { opacity: 0, x: 40 },
    visible: { opacity: 1, x: 0 },
  },
  fadeRight: {
    hidden: { opacity: 0, x: -40 },
    visible: { opacity: 1, x: 0 },
  },
  scaleUp: {
    hidden: { opacity: 0, scale: 0.8 },
    visible: { opacity: 1, scale: 1 },
  },
  scaleDown: {
    hidden: { opacity: 0, scale: 1.2 },
    visible: { opacity: 1, scale: 1 },
  },
};

/**
 * ScrollReveal - Wrapper component that animates children when scrolling into view
 *
 * Features:
 * - Multiple animation variants (fade, slide, scale)
 * - Configurable duration and delay
 * - Triggers only when element is in viewport
 * - Respects prefers-reduced-motion
 * - Optimized for performance
 *
 * @example
 * <ScrollReveal variant="fadeUp" delay={0.2}>
 *   <h2>This will fade up when scrolled into view</h2>
 * </ScrollReveal>
 */
export const ScrollReveal: React.FC<ScrollRevealProps> = ({
  children,
  variant = 'fadeUp',
  duration = 0.6,
  delay = 0,
  once = true,
  amount = 0.3,
  className = '',
  disabled = false,
}) => {
  const ref = React.useRef<HTMLDivElement>(null);
  const isInView = useInView(ref, { once, amount });

  // Check for prefers-reduced-motion
  const prefersReducedMotion =
    typeof window !== 'undefined' &&
    window.matchMedia('(prefers-reduced-motion: reduce)').matches;

  if (disabled || prefersReducedMotion) {
    return <div className={className}>{children}</div>;
  }

  const selectedVariants = variants[variant];

  return (
    <motion.div
      ref={ref}
      className={className}
      initial="hidden"
      animate={isInView ? 'visible' : 'hidden'}
      variants={selectedVariants}
      transition={{
        duration,
        delay,
        ease: [0.25, 0.1, 0.25, 1], // Custom easing for smoother animation
      }}
    >
      {children}
    </motion.div>
  );
};

export default ScrollReveal;
