import { useState, useCallback, useEffect, createContext, useContext, ReactNode } from 'react';
import { Undo2, X } from 'lucide-react';

interface UndoableAction {
    id: string;
    label: string;
    undo: () => Promise<void>;
    timestamp: number;
}

interface UndoContextType {
    pushAction: (label: string, undoFn: () => Promise<void>) => void;
    canUndo: boolean;
    undoLast: () => void;
}

const UndoContext = createContext<UndoContextType | null>(null);

const UNDO_WINDOW_MS = 5000; // 5 seconds to undo

export function UndoProvider({ children }: { children: ReactNode }) {
    const [actions, setActions] = useState<UndoableAction[]>([]);
    const [isUndoing, setIsUndoing] = useState(false);

    // Clean up expired actions
    useEffect(() => {
        const interval = setInterval(() => {
            const now = Date.now();
            setActions(prev => prev.filter(a => now - a.timestamp < UNDO_WINDOW_MS));
        }, 1000);
        return () => clearInterval(interval);
    }, []);

    const pushAction = useCallback((label: string, undoFn: () => Promise<void>) => {
        const action: UndoableAction = {
            id: crypto.randomUUID(),
            label,
            undo: undoFn,
            timestamp: Date.now()
        };
        setActions(prev => [...prev, action]);
    }, []);

    const undoLast = useCallback(async () => {
        const lastAction = actions[actions.length - 1];
        if (!lastAction || isUndoing) return;

        setIsUndoing(true);
        try {
            await lastAction.undo();
            setActions(prev => prev.filter(a => a.id !== lastAction.id));
        } catch (e) {
            console.error('Undo failed:', e);
        } finally {
            setIsUndoing(false);
        }
    }, [actions, isUndoing]);

    const dismissAction = useCallback((id: string) => {
        setActions(prev => prev.filter(a => a.id !== id));
    }, []);

    return (
        <UndoContext.Provider value={{ pushAction, canUndo: actions.length > 0, undoLast }}>
            {children}

            {/* Undo toast */}
            {actions.length > 0 && (
                <div className="fixed bottom-24 md:bottom-8 left-1/2 -translate-x-1/2 z-50 animate-slide-up">
                    {actions.slice(-1).map(action => (
                        <UndoToast
                            key={action.id}
                            action={action}
                            onUndo={() => undoLast()}
                            onDismiss={() => dismissAction(action.id)}
                            isUndoing={isUndoing}
                        />
                    ))}
                </div>
            )}
        </UndoContext.Provider>
    );
}

function UndoToast({
    action,
    onUndo,
    onDismiss,
    isUndoing
}: {
    action: UndoableAction;
    onUndo: () => void;
    onDismiss: () => void;
    isUndoing: boolean;
}) {
    const [progress, setProgress] = useState(100);

    useEffect(() => {
        const elapsed = Date.now() - action.timestamp;
        const remaining = UNDO_WINDOW_MS - elapsed;

        if (remaining <= 0) {
            onDismiss();
            return;
        }

        setProgress((remaining / UNDO_WINDOW_MS) * 100);

        const interval = setInterval(() => {
            const now = Date.now();
            const newRemaining = UNDO_WINDOW_MS - (now - action.timestamp);
            if (newRemaining <= 0) {
                onDismiss();
            } else {
                setProgress((newRemaining / UNDO_WINDOW_MS) * 100);
            }
        }, 100);

        return () => clearInterval(interval);
    }, [action.timestamp, onDismiss]);

    return (
        <div className="bg-slate-900 dark:bg-slate-700 text-white px-4 py-3 rounded-xl shadow-2xl flex items-center gap-4 min-w-[280px] relative overflow-hidden">
            {/* Progress bar */}
            <div
                className="absolute bottom-0 left-0 h-1 bg-[var(--color-primary)] transition-all duration-100"
                style={{ width: `${progress}%` }}
            />

            <span className="text-sm flex-1">{action.label}</span>

            <button
                onClick={onUndo}
                disabled={isUndoing}
                className="flex items-center gap-1.5 px-3 py-1 bg-white/10 hover:bg-white/20 disabled:opacity-50 rounded-lg text-sm font-medium transition-colors"
            >
                <Undo2 size={14} />
                Undo
            </button>

            <button
                onClick={onDismiss}
                className="p-1 hover:bg-white/10 rounded transition-colors"
            >
                <X size={16} />
            </button>
        </div>
    );
}

export function useUndo() {
    const context = useContext(UndoContext);
    if (!context) {
        throw new Error('useUndo must be used within UndoProvider');
    }
    return context;
}
