import { createContext, useContext, useState, useCallback, ReactNode } from 'react';
import { Alert, AlertDescription } from './Alert';

export type ToastVariant = 'default' | 'success' | 'error' | 'warning' | 'info';

export interface Toast {
  id: string;
  title?: string;
  message: string;
  variant: ToastVariant;
  duration?: number;
}

interface ToastContextType {
  toasts: Toast[];
  addToast: (toast: Omit<Toast, 'id'>) => void;
  removeToast: (id: string) => void;
  success: (message: string, title?: string) => void;
  error: (message: string, title?: string) => void;
  warning: (message: string, title?: string) => void;
  info: (message: string, title?: string) => void;
}

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

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

export function ToastProvider({ children }: { children: ReactNode }): JSX.Element {
  const [toasts, setToasts] = useState<Toast[]>([]);

  const removeToast = useCallback((id: string): void => {
    setToasts((prev) => prev.filter((toast) => toast.id !== id));
  }, []);

  const addToast = useCallback(
    (toast: Omit<Toast, 'id'>): void => {
      const id = Math.random().toString(36).substring(2, 9);
      const newToast: Toast = {
        ...toast,
        id,
        duration: toast.duration || 5000,
      };

      setToasts((prev) => [...prev, newToast]);

      if (newToast.duration && newToast.duration > 0) {
        if (typeof window !== 'undefined') {
          setTimeout(() => {
            removeToast(id);
          }, newToast.duration);
        }
      }
    },
    [removeToast]
  );

  const success = useCallback(
    (message: string, title?: string): void => {
      addToast({ message, title, variant: 'success' });
    },
    [addToast]
  );

  const error = useCallback(
    (message: string, title?: string): void => {
      addToast({ message, title, variant: 'error' });
    },
    [addToast]
  );

  const warning = useCallback(
    (message: string, title?: string): void => {
      addToast({ message, title, variant: 'warning' });
    },
    [addToast]
  );

  const info = useCallback(
    (message: string, title?: string): void => {
      addToast({ message, title, variant: 'info' });
    },
    [addToast]
  );

  return (
    <ToastContext.Provider value={{ toasts, addToast, removeToast, success, error, warning, info }}>
      {children}
      <ToastContainer toasts={toasts} removeToast={removeToast} />
    </ToastContext.Provider>
  );
}

function ToastContainer({ toasts, removeToast }: { toasts: Toast[]; removeToast: (id: string) => void }): JSX.Element | null {
  if (toasts.length === 0) return null;

  return (
    <div className="fixed top-4 right-4 z-50 flex flex-col gap-2 w-full max-w-sm">
      {toasts.map((toast) => (
        <ToastItem key={toast.id} toast={toast} onRemove={removeToast} />
      ))}
    </div>
  );
}

function ToastItem({ toast, onRemove }: { toast: Toast; onRemove: (id: string) => void }): JSX.Element {
  const variantMap: Record<ToastVariant, { alert: 'default' | 'destructive' | 'success' | 'warning'; icon: string }> = {
    default: { alert: 'default', icon: 'ℹ️' },
    success: { alert: 'success', icon: '✓' },
    error: { alert: 'destructive', icon: '✗' },
    warning: { alert: 'warning', icon: '⚠' },
    info: { alert: 'default', icon: 'ℹ️' },
  };

  const variant = variantMap[toast.variant];

  return (
    <Alert
      variant={variant.alert}
      className="animate-in slide-in-from-top-5 fade-in shadow-lg"
    >
      <div className="flex items-start justify-between">
        <div className="flex-1">
          {toast.title && (
            <AlertDescription className="font-semibold mb-1">{toast.title}</AlertDescription>
          )}
          <AlertDescription>{toast.message}</AlertDescription>
        </div>
        <button
          onClick={() => onRemove(toast.id)}
          className="ml-4 text-gray-500 hover:text-gray-700 text-xl leading-none"
          aria-label="Close"
        >
          ×
        </button>
      </div>
    </Alert>
  );
}

