'use client';

import React, { useEffect, useState } from 'react';
import { ToastProps, RichColorsMode, ToastSize } from '../types';
import { useToastContext } from '../context/ToastContext';
import { DEFAULT_DURATION } from '../utils/constants';
import { X, CheckCircle, AlertCircle, Info, AlertTriangle, Loader2 } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import ToastProgressBar from '../utils/ToastProgressBar';

interface ToastComponentProps extends ToastProps {
  isExpanded: boolean;
  isStacked: boolean;
  showCloseButton?: boolean;
  showProgressBar?: boolean;
  richColors?: RichColorsMode;
  size?: ToastSize;
}

export const Toast: React.FC<ToastComponentProps> = ({
  id,
  content,
  description,
  type,
  status,
  duration = DEFAULT_DURATION,
  icon,
  actions,
  input,
  onClose,
  onClick,
  progress,
  customStyles,
  className = '',
  isExpanded,
  isStacked,
  showCloseButton,
  showProgressBar,
  size = 'md',
  priority = 'normal',
  expandable = false,
  expanded: controlledExpanded,
  customComponent,
  unstyled = false,
  cancel,
  richColors,
}) => {
  const { removeToast, updateToast } = useToastContext();
  const [inputValue, setInputValue] = useState('');
  const [localProgress, setLocalProgress] = useState(progress || 100);
  const [isPaused, setIsPaused] = useState(false);
  const [internalExpanded, setInternalExpanded] = useState(false);
  const startTimeRef = React.useRef<number>(Date.now());
  const elapsedWhenPausedRef = React.useRef<number>(0);
  const animationFrameRef = React.useRef<number | null>(null);
  const isInitialMountRef = React.useRef<boolean>(true);
  const removeTimeoutRef = React.useRef<NodeJS.Timeout | null>(null);

  const { color } = useToastContext();

  // Handle expanded state
  const isExpandedState = controlledExpanded !== undefined ? controlledExpanded : internalExpanded;
  
  // Determine actual status (for promise-based toasts)
  const actualStatus = status || (type === 'success' ? 'success' : type === 'error' ? 'error' : 'idle');

  // Improved progress bar with pause on hover and better accuracy
  useEffect(() => {
    if (typeof progress !== 'undefined') {
      setLocalProgress(progress);
      return;
    }

    // If duration is 0, don't auto-dismiss (for loading/promise toasts)
    if (duration === 0) {
      setLocalProgress(100); // Keep at 100% (no progress bar animation)
      return;
    }

    // Initialize start time on first mount
    if (isInitialMountRef.current) {
      startTimeRef.current = Date.now();
      isInitialMountRef.current = false;
    }

    // Adjust start time when resuming from pause
    if (!isPaused && elapsedWhenPausedRef.current > 0) {
      startTimeRef.current = Date.now() - elapsedWhenPausedRef.current;
    }

    const updateProgress = () => {
      if (isPaused) {
        // Store elapsed time when paused
        elapsedWhenPausedRef.current = Date.now() - startTimeRef.current;
        return;
      }

      const elapsed = Date.now() - startTimeRef.current;
      const progressValue = Math.max(0, Math.min(100, 100 - (elapsed / duration) * 100));
      
      setLocalProgress(progressValue);

      // Remove toast when progress is very close to 0 (account for animation lag)
      // This ensures progress bar completes before toast disappears
      if (progressValue <= 1) {
        setLocalProgress(0); // Ensure progress is exactly 0
        // Clear any pending timeout
        if (removeTimeoutRef.current !== null) {
          clearTimeout(removeTimeoutRef.current);
        }
        // Very small delay to let progress bar complete its animation
        removeTimeoutRef.current = setTimeout(() => {
          removeToast(id);
        }, 50);
      } else {
        animationFrameRef.current = requestAnimationFrame(updateProgress);
      }
    };

    if (!isPaused && duration > 0) {
      animationFrameRef.current = requestAnimationFrame(updateProgress);
    }

    return () => {
      if (animationFrameRef.current !== null) {
        cancelAnimationFrame(animationFrameRef.current);
      }
      if (removeTimeoutRef.current !== null) {
        clearTimeout(removeTimeoutRef.current);
      }
    };
  }, [duration, progress, isPaused, id, removeToast]);

  const getIcon = () => {
    // Show loading spinner for loading status (priority over custom icon)
    if (actualStatus === 'loading' || status === 'loading') {
      return (
        <Loader2 
          className="vyrn-toast-icon w-5 h-5 vyrn-toast-icon-loading" 
          aria-hidden="true"
        />
      );
    }
    
    if (icon) return icon;
    
    switch (type) {
      case 'success':
        return <CheckCircle className="vyrn-toast-icon w-5 h-5" aria-hidden="true" />;
      case 'error':
        return <AlertCircle className="vyrn-toast-icon w-5 h-5" aria-hidden="true" />;
      case 'info':
        return <Info className="vyrn-toast-icon w-5 h-5" aria-hidden="true" />;
      case 'warning':
        return <AlertTriangle className="vyrn-toast-icon w-5 h-5" aria-hidden="true" />;
      default:
        return null;
    }
  };

  const handleClose = () => {
    onClose?.();
    removeToast(id);
  };

  const handleClick = () => {
    if (onClick) {
      onClick();
    } else if (expandable) {
      setInternalExpanded(!internalExpanded);
    }
  };

  const handleCancel = () => {
    cancel?.onClick?.();
    handleClose();
  };

  // Render custom component if provided
  if (customComponent) {
    const CustomComponent = customComponent;
    return (
      <CustomComponent
        toast={{
          id,
          content,
          description,
          type,
          status: actualStatus,
          duration,
          icon,
          actions,
          input,
          onClose,
          onClick,
          progress,
          customStyles,
          className,
          showCloseButton,
          swipeClose: true,
          showProgressBar,
          priority,
          expandable,
          expanded: isExpandedState,
        }}
        dismiss={handleClose}
      />
    );
  }

  const handleInputSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    input?.onSubmit(inputValue);
    setInputValue('');
  };

  const getRole = () => {
    switch (type) {
      case 'error':
        return 'alert';
      case 'success':
      case 'info':
      case 'warning':
        return 'status';
      default:
        return 'status';
    }
  };

  const toastClasses = [
    'vyrn-toast',
    className,
    isStacked ? 'vyrn-toast-stacked' : '',
    color && type && !richColors ? `vyrn-toast-${type}` : '',
    richColors && type ? `vyrn-toast-rich-${type}` : '',
    richColors ? `vyrn-toast-rich-mode-${richColors}` : '',
    `vyrn-toast-size-${size}`,
    actualStatus === 'loading' ? 'vyrn-toast-loading' : '',
    actualStatus === 'success' ? 'vyrn-toast-success-state' : '',
    actualStatus === 'error' ? 'vyrn-toast-error-state' : '',
    priority === 'high' ? 'vyrn-toast-priority-high' : '',
    priority === 'low' ? 'vyrn-toast-priority-low' : '',
    expandable ? 'vyrn-toast-expandable' : '',
    isExpandedState ? 'vyrn-toast-expanded' : '',
    unstyled ? 'vyrn-toast-unstyled' : '',
    onClick || expandable ? 'vyrn-toast-clickable' : '',
  ]
    .filter(Boolean)
    .join(' ');

  return (
    <motion.div
      className={toastClasses}
      style={{
        ...customStyles,
        height: isExpandedState ? 'auto' : isStacked ? '60px' : 'auto',
        overflow: 'hidden',
        maxHeight: isStacked ? '60px' : 'none',
        ...(isStacked && type === 'custom' ? {
          display: 'flex',
          flexDirection: 'column',
        } : {}),
      }}
      initial={{ opacity: 0, y: 20, scale: 0.95 }}
      animate={{ 
        opacity: 1, 
        y: 0, 
        scale: 1,
      }}
      exit={{ opacity: 0, scale: 0.8, y: -20, transition: { duration: 0.2 } }}
      transition={{ 
        type: 'spring', 
        stiffness: 400, 
        damping: 30,
        mass: 0.8,
      }}
      role={getRole()}
      aria-live={type === 'error' ? 'assertive' : 'polite'}
      aria-atomic="true"
      aria-expanded={expandable ? isExpandedState : undefined}
      onMouseEnter={() => setIsPaused(true)}
      onMouseLeave={() => setIsPaused(false)}
      onClick={handleClick}
      whileHover={onClick || expandable ? { scale: 1.02 } : undefined}
      whileTap={onClick || expandable ? { scale: 0.98 } : undefined}
    >
      <div className="vyrn-toast-content">
        {getIcon()}
        <div className="vyrn-toast-message-wrapper">
          <div 
            className={`vyrn-toast-message ${isStacked && type === 'custom' ? 'vyrn-toast-message-stacked-custom' : ''}`}
            role="text"
            style={isStacked && type === 'custom' ? { 
              overflow: 'hidden',
              maxHeight: '40px',
              display: '-webkit-box',
              WebkitLineClamp: 2,
              WebkitBoxOrient: 'vertical',
              lineHeight: '20px',
              wordBreak: 'break-word',
            } : isStacked ? { 
              overflow: 'hidden',
              textOverflow: 'ellipsis',
              whiteSpace: 'nowrap',
              maxWidth: '100%',
            } : {}}
          >
            {content}
          </div>
          {description && !isStacked && (
            <div className="vyrn-toast-description" role="text">{description}</div>
          )}
        </div>
      </div>
      <AnimatePresence>
        {isExpandedState && (
          <motion.div
            initial={{ opacity: 0, height: 0 }}
            animate={{ opacity: 1, height: 'auto' }}
            exit={{ opacity: 0, height: 0 }}
            transition={{ duration: 0.3 }}
          >
            {actions && (
              <div className="vyrn-toast-actions">
                {actions.map((action, index) => (
                  <button
                    key={index}
                    onClick={(e) => {
                      e.stopPropagation();
                      action.onClick();
                    }}
                    className={`vyrn-toast-action vyrn-toast-action-${action.style || 'default'} ${
                      action.className || ''
                    }`}
                    aria-label={action.label}
                  >
                    {action.label}
                  </button>
                ))}
              </div>
            )}
            {input && (
              <form onSubmit={handleInputSubmit} className="vyrn-toast-input-form">
                <input
                  type="text"
                  value={inputValue}
                  onChange={(e) => setInputValue(e.target.value)}
                  placeholder={input.placeholder}
                  className={`vyrn-toast-input ${input.className || ''}`}
                  onClick={(e) => e.stopPropagation()}
                  aria-label={input.placeholder}
                />
                <button
                  type="submit"
                  className={`vyrn-toast-input-submit ${input.submitClassName || ''}`}
                  onClick={(e) => e.stopPropagation()}
                  aria-label="Submit"
                >
                  Submit
                </button>
              </form>
            )}
            {cancel && (
              <div className="vyrn-toast-cancel">
                <button
                  onClick={(e) => {
                    e.stopPropagation();
                    handleCancel();
                  }}
                  className="vyrn-toast-cancel-button"
                  aria-label={cancel.label}
                >
                  {cancel.label}
                </button>
              </div>
            )}
          </motion.div>
        )}
      </AnimatePresence>
      {showCloseButton && (
        <button
          className="vyrn-toast-close"
          onClick={(e) => {
            e.stopPropagation();
            handleClose();
          }}
          aria-label="Close"
        >
          <X size={18} aria-hidden="true" />
        </button>
      )}
      {showProgressBar && (
        <ToastProgressBar
          progress={localProgress}
          type={type as 'success' | 'error' | 'warning' | 'info' | 'default'}
        />
      )}
     
    </motion.div>
  );
};
