import React, { useState, useRef, useEffect } from 'react';
import { Toast } from './Toast';
import { ToastProps, ToastPosition, ToastLayout, RichColorsMode, ToastSize } from '../types';
import { AnimatePresence, motion } from 'framer-motion';

interface ToastContainerProps {
  toasts: ToastProps[];
  position: ToastPosition;
  layout: ToastLayout;
  className?: string;
  showCloseButton?: boolean;
  swipeDirection?: 'left' | 'right' | 'up' | 'down';
  showProgressBar?: boolean;
  color?: boolean;
  richColors?: RichColorsMode;
  size?: ToastSize;
  onRemoveToast: (id: string) => void;
}

export const ToastContainer: React.FC<ToastContainerProps> = ({
  toasts,
  position,
  layout,
  className = '',
  showCloseButton = true,
  swipeDirection = 'right',
  showProgressBar = true,
  color = true,
  richColors,
  size = 'md',
  onRemoveToast,
}) => {
  const [isHovered, setIsHovered] = useState(false);
  const [isMobile, setIsMobile] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const toastHeightsRef = useRef<Map<string, number>>(new Map());
  const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  
  // Sonner-like spacing: simple and consistent
  const STACK_GAP = 10; // Tight visible gap when stacked (like Sonner - toasts overlap)
  const EXPANDED_GAP = 8; // Consistent gap when expanded (like Sonner)
  const BASE_TOAST_HEIGHT = 64; // Base toast height (content + padding)

  // Detect mobile on mount and resize
  useEffect(() => {
    const checkMobile = () => {
      setIsMobile(window.innerWidth < 640);
    };
    
    checkMobile();
    window.addEventListener('resize', checkMobile);
    return () => window.removeEventListener('resize', checkMobile);
  }, []);
  
  // Calculate toast height based on content
  const getToastHeight = (toast: ToastProps, isExpanded: boolean): number => {
    if (!isExpanded && layout === 'stack') {
      return 60; // Stacked height
    }
    
    let height = BASE_TOAST_HEIGHT; // Base height
    
    // Custom toasts with JSX content need more height
    if (toast.type === 'custom') {
      height += 20; // Custom content typically needs more space
    }
    
    // Add height for description
    if (toast.description) {
      height += 20; // Description adds ~20px
    }
    
    // Add height for actions
    if (toast.actions && toast.actions.length > 0) {
      height += 40; // Actions add ~40px
    }
    
    // Add height for input
    if (toast.input) {
      height += 40; // Input adds ~40px
    }
    
    // Add height for cancel button
    if (toast.cancel) {
      height += 32; // Cancel button adds ~32px
    }
    
    return height;
  };

  const getPositionStyles = () => {
    const styles: React.CSSProperties = { position: 'fixed', zIndex: 9999 };
    // Use responsive values that work better on mobile
    const topOffset = isMobile ? '0.5rem' : '1rem';
    // For bottom positions, add extra space when using stack layout to prevent going off-screen
    const baseBottomOffset = isMobile ? '1rem' : '3.5rem';
    // When stack layout is used with bottom position, add more space to account for stacked toasts
    // This ensures toasts don't go off-screen when stacked
    // Mobile needs more space due to smaller screen and potential navigation bars
    const bottomOffset = layout === 'stack' && position.includes('bottom')
      ? (isMobile ? '4.5rem' : '5.5rem') // Increased space for stack layout (more for mobile)
      : baseBottomOffset;
    const sideOffset = isMobile ? '0.5rem' : '1rem';
    
    if (position.includes('top')) styles.top = topOffset;
    if (position.includes('bottom')) styles.bottom = bottomOffset;
    if (position.includes('left')) styles.left = sideOffset;
    if (position.includes('right')) styles.right = sideOffset;
    if (position.includes('center')) {
      styles.left = '50%';
      styles.transform = 'translateX(-50%)';
      // Adjust for mobile
      if (isMobile) {
        styles.width = 'calc(100% - 1rem)';
        styles.maxWidth = '100%';
      }
    }
    return styles;
  };

  const getSwipeAnimation = () => {
    const distance = 100;
    switch (swipeDirection) {
      case 'left':
        return { x: -distance, opacity: 0 };
      case 'right':
        return { x: distance, opacity: 0 };
      case 'up':
        return { y: -distance, opacity: 0 };
      case 'down':
        return { y: distance, opacity: 0 };
      default:
        return { x: distance, opacity: 0 };
    }
  };

  // Reverse toasts array for proper stacking order
  const reversedToasts = [...toasts].reverse();

  const getOffset = (index: number) => {
    if (layout === 'normal') {
      // Normal layout: consistent spacing
      const gap = isHovered ? 12 : 8;
      return position.startsWith('top') ? index * gap : -(index * gap);
    }

    if (layout === 'stack') {
      if (isHovered) {
        // When hovered, calculate cumulative offset based on actual toast heights
        let offset = 0;
        for (let i = 0; i < index; i++) {
          const prevToast = reversedToasts[i];
          const prevHeight = getToastHeight(prevToast, true);
          offset += prevHeight + EXPANDED_GAP;
        }
        return offset;
      } else {
        // When stacked, tight spacing (toasts overlap, only small portion visible)
        return index * STACK_GAP;
      }
    }

    return 0;
  };

  return (
    <div
      className={`vyrn-toast-container ${className}`}
      style={getPositionStyles()}
      ref={containerRef}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
      aria-live="polite"
      aria-label="Notifications"
    >
      <AnimatePresence mode="popLayout">
        {reversedToasts.map((toast, index) => {
          const isExpanded = toast.expanded !== undefined 
            ? toast.expanded 
            : (layout !== 'stack' || isHovered);
          const isStacked = layout === 'stack' && !isHovered;
          const offset = getOffset(index);
          
          return (
            <motion.div
              key={toast.id}
              layout
              layoutId={toast.id}
              initial={{ opacity: 0, y: position.startsWith('top') ? -20 : 20, scale: 0.95 }}
              animate={{
                opacity: 1,
                y: position.startsWith('top') ? offset : -offset,
                scale: isStacked ? 0.96 : 1,
                zIndex: layout === 'stack' ? 9999 - index : 9999,
              }}
              exit={getSwipeAnimation()}
              transition={{
                layout: {
                  type: 'spring',
                  stiffness: 400,
                  damping: 30,
                  mass: 0.8,
                },
                opacity: { duration: 0.15 },
                scale: { 
                  type: 'spring',
                  stiffness: 400,
                  damping: 30,
                },
                y: {
                  type: 'spring',
                  stiffness: 400,
                  damping: 30,
                  mass: 0.8,
                },
              }}
              drag={swipeDirection === 'left' || swipeDirection === 'right' ? 'x' : 'y'}
              dragConstraints={{ left: 0, right: 0, top: 0, bottom: 0 }}
              dragElastic={0.2}
              dragDirectionLock={true}
              onDragEnd={(_, info) => {
                // Lower threshold on mobile for easier swiping
                const threshold = isMobile ? 50 : 100;
                const velocity = isMobile ? 200 : 500;
                
                // Check if dragged far enough or fast enough
                if (
                  Math.abs(info.offset.x) > threshold || 
                  Math.abs(info.offset.y) > threshold ||
                  Math.abs(info.velocity.x) > velocity ||
                  Math.abs(info.velocity.y) > velocity
                ) {
                  toast.onClose?.();
                  onRemoveToast(toast.id);
                }
              }}
              style={{
                position: layout === 'normal' ? 'relative' : 'absolute',
                width: '100%',
                transformOrigin: position.startsWith('top') ? 'top' : 'bottom',
                marginBottom: layout === 'normal' ? (isHovered ? 12 : 8) : 0,
              }}
            >
              <Toast
                {...toast}
                isExpanded={isExpanded}
                isStacked={isStacked}
                showCloseButton={toast.showCloseButton ?? showCloseButton}
                showProgressBar={toast.showProgressBar ?? showProgressBar}
                richColors={richColors}
                size={toast.size ?? size}
              />
            </motion.div>
          );
        })}
      </AnimatePresence>
    </div>
  );
};
