import React, { createContext, useContext, useEffect, useReducer, useRef } from 'react';
import { Toast } from './Toast';

type ToastType = 'success' | 'error' | 'warning' | 'info';

export interface ToastMessage {
  id: string;
  message: string;
  type: ToastType;
  duration?: number;
  details?: string;
}

export interface ToastContextType {
  addToast: (message: string, type: ToastType, duration?: number, details?: string) => void;
  removeToast: (id: string) => void;
}

const ToastContext = createContext<ToastContextType | undefined>(undefined);

type ToastAction = 
  | { type: 'ADD_TOAST'; payload: ToastMessage }
  | { type: 'REMOVE_TOAST'; payload: string }
  | { type: 'SET_HOVERED_TOAST', payload: { id: string, hovered: boolean } };

const toastReducer = (state: ToastMessage[], action: ToastAction): ToastMessage[] => {
  switch (action.type) {
    case 'ADD_TOAST':
      return [...state, { ...action.payload, hovered: false }];
    case 'REMOVE_TOAST':
      return state.filter(toast => toast.id !== action.payload);
    case 'SET_HOVERED_TOAST':
      return state.map(toast => 
        toast.id === action.payload.id 
          ? { ...toast, hovered: action.payload.hovered } 
          : toast
      );
    default:
      return state;
  }
};

export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [toasts, dispatch] = useReducer(toastReducer, []);
  const hoverTimeouts = useRef<Record<string, NodeJS.Timeout>>({});

  const addToast = (message: string, type: ToastType, duration: number = 5000, details?: string) => {
    const id = Date.now().toString();
    dispatch({ type: 'ADD_TOAST', payload: { id, message, type, duration, details } });
  };

  const removeToast = (id: string) => {
    dispatch({ type: 'REMOVE_TOAST', payload: id });
  };

  const setToastHovered = (id: string, hovered: boolean) => {
    dispatch({ type: 'SET_HOVERED_TOAST', payload: { id, hovered } });
  };

  // Auto remove toasts after duration, but respect hover state
  useEffect(() => {
    const timers = toasts.map(toast => {
      // Clear any existing timeout for this toast
      if (hoverTimeouts.current[toast.id]) {
        clearTimeout(hoverTimeouts.current[toast.id]);
        delete hoverTimeouts.current[toast.id];
      }

      // If toast is hovered, don't set a timer
      if (toast.hovered) {
        return null;
      }

      // If duration is 0, it's persistent
      if (toast.duration === 0) {
        return null;
      }

      // Set timeout to remove toast
      const timeout = setTimeout(() => {
        removeToast(toast.id);
      }, toast.duration);

      return { id: toast.id, timeout };
    });

    // Cleanup function
    return () => {
      timers.forEach(timer => {
        if (timer) clearTimeout(timer.timeout);
      });
    };
  }, [toasts]);

  return (
    <ToastContext.Provider value={{ addToast, removeToast }}>
      {children}
      <div className="fixed top-4 right-4 z-50 space-y-2">
        {toasts.map(toast => (
          <div 
            key={toast.id} 
            className="animate-in slide-in-from-right duration-300"
          >
            <Toast
              id={toast.id}
              message={toast.message}
              type={toast.type}
              details={toast.details}
              onClose={removeToast}
              onHoverChange={(hovered) => setToastHovered(toast.id, hovered)}
            />
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
};

export const useToast = () => {
  const context = useContext(ToastContext);
  if (!context) {
    throw new Error('useToast must be used within a ToastProvider');
  }
  return context;
};