"use client";
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useTransition } from "react";
import { useRouter } from "next/navigation";
import { Undo2, X } from "lucide-react";
import { restoreImages } from "@/app/actions/trash";

interface ToastState {
  ids: number[];
  visibleAt: number;
  failed?: { message: string };
}

interface Ctx {
  show: (ids: number[]) => void;
}

const ToastCtx = createContext<Ctx | null>(null);
const VISIBLE_MS = 8000;

export function UndoDeleteToastProvider({ children }: { children: React.ReactNode }) {
  const [state, setState] = useState<ToastState | null>(null);
  const timerRef = useRef<number | null>(null);
  const router = useRouter();
  const [pending, start] = useTransition();

  const dismiss = useCallback(() => {
    setState(null);
    if (timerRef.current != null) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
  }, []);

  const show = useCallback((ids: number[]) => {
    if (ids.length === 0) return;
    setState({ ids, visibleAt: Date.now() });
    if (timerRef.current != null) clearTimeout(timerRef.current);
    timerRef.current = window.setTimeout(() => setState(null), VISIBLE_MS);
  }, []);

  useEffect(() => () => { if (timerRef.current != null) clearTimeout(timerRef.current); }, []);

  const undo = () => {
    if (!state) return;
    const ids = state.ids;
    // Hide the trash-confirmation copy while the restore is in flight,
    // but DON'T dismiss the toast — if restoreImages throws, the items
    // are still in trash and the user has no signal. Re-surface in the
    // catch with a retry affordance.
    if (timerRef.current != null) {
      clearTimeout(timerRef.current);
      timerRef.current = null;
    }
    start(async () => {
      try {
        await restoreImages(ids);
        router.refresh();
        setState(null);
      } catch (e) {
        setState({
          ids,
          visibleAt: Date.now(),
          failed: { message: (e as Error).message || "Restore failed" },
        });
        timerRef.current = window.setTimeout(() => setState(null), VISIBLE_MS);
      }
    });
  };

  const ctx = useMemo<Ctx>(() => ({ show }), [show]);

  return (
    <ToastCtx.Provider value={ctx}>
      {children}
      {state && (
        <div className="fixed bottom-[80px] left-1/2 -translate-x-1/2 z-[60]">
          <div
            className="rounded-2xl shadow-2xl px-4 py-2.5 flex items-center gap-3 border border-[var(--color-glass-border-strong)] backdrop-blur-2xl"
            style={{ background: "color-mix(in oklch, var(--color-bg-0) 90%, transparent)" }}
          >
            <span className="text-sm">
              {state.failed ? (
                <>
                  <span className="text-[var(--color-red)]">Restore failed</span>
                  <span className="text-[var(--color-fg-dim)]"> &mdash; {state.failed.message}</span>
                </>
              ) : (
                <>
                  <span className="font-mono text-[var(--color-cyan)]">{state.ids.length}</span>
                  <span className="text-[var(--color-fg-dim)]"> moved to trash</span>
                </>
              )}
            </span>
            <div className="w-px h-5 bg-[var(--color-glass-border)]" />
            <button
              onClick={undo}
              disabled={pending}
              className="flex items-center gap-1.5 text-xs px-3 py-1.5 rounded-lg bg-[var(--color-cyan)]/15 text-[var(--color-cyan)] border border-[var(--color-cyan)]/40 hover:bg-[var(--color-cyan)]/25 disabled:opacity-50"
            >
              <Undo2 className="w-3.5 h-3.5" /> {state.failed ? "Retry" : "Undo"}
            </button>
            <button
              onClick={dismiss}
              aria-label="Dismiss"
              className="text-[var(--color-fg-muted)] hover:text-[var(--color-fg)]"
            >
              <X className="w-3.5 h-3.5" />
            </button>
          </div>
        </div>
      )}
    </ToastCtx.Provider>
  );
}

export function useUndoDeleteToast() {
  const ctx = useContext(ToastCtx);
  if (!ctx) throw new Error("useUndoDeleteToast must be used within UndoDeleteToastProvider");
  return ctx;
}
