import { Sheet, SheetContent } from "@repo/shadcn-ui/components";
// hooks/use-pinned-preview-sheet.ts
import * as React from "react";
import { createPortal } from 'react-dom';

type UsePinnedPreviewSheetOptions<T> = {
    persistKey?: string;              // clave localStorage para “pin”
    widthClass?: string;              // ancho del panel: p. ej. "w-[500px]"
    onOpenChange?: (open: boolean) => void;
    title?: string | ((item: T | null) => string); // Título del Sheet (no anclado)
};

export type PinnedPreviewSheet<T> = {
    /** Estado */
    isOpen: boolean;
    isPinned: boolean;
    item: T | null;
    open: (item: T) => void;
    close: () => void;
    togglePin: () => void;

    /** Añade margen al contenedor de la lista cuando está anclado */
    listRightMarginClass: string;

    /** Renderiza el panel (Sheet o aside) */
    Preview: React.FC<{
        children: (ctx: {
            item: T;
            isPinned: boolean;
            close: () => void;
            togglePin: () => void;
        }) => React.ReactNode
    }>;
};

export function usePinnedPreviewSheet<T = unknown>({
    persistKey = "preview-pin",
    widthClass = "w-[500px]",
    onOpenChange,
    title,
}: UsePinnedPreviewSheetOptions<T> = {}): PinnedPreviewSheet<T> {
    const [isOpen, setOpen] = React.useState(false);
    const [item, setItem] = React.useState<T | null>(null);
    const [isPinned, setPinned] = React.useState<boolean>(() => {
        try { return localStorage.getItem(persistKey) === "1"; } catch { return false; }
    });

    // recordar/restaurar foco para accesibilidad
    const lastFocused = React.useRef<HTMLElement | null>(null);
    const rememberFocus = () => { lastFocused.current = document.activeElement as HTMLElement | null; };
    const restoreFocus = () => { lastFocused.current?.focus?.(); };

    const open = React.useCallback((next: T) => {
        rememberFocus();
        setItem(next);
        setOpen(true);
        onOpenChange?.(true);
    }, [onOpenChange]);

    const close = React.useCallback(() => {
        if (isPinned) return;
        setOpen(false);
        onOpenChange?.(false);
        setTimeout(restoreFocus, 0);
    }, [isPinned, onOpenChange]);

    const togglePin = React.useCallback(() => {
        setPinned((p) => {
            const n = !p;
            try { localStorage.setItem(persistKey, n ? "1" : "0"); } catch { }
            return n;
        });
    }, [persistKey]);

    // Bloquea scroll solo en modo Sheet
    React.useEffect(() => {
        if (isOpen && !isPinned) {
            const prev = document.body.style.overflow;
            document.body.style.overflow = "hidden";
            return () => { document.body.style.overflow = prev; };
        }
    }, [isOpen, isPinned]);

    // Cerrar con ESC solo en modo Sheet
    React.useEffect(() => {
        if (!isOpen || isPinned) return;
        const onKey = (e: KeyboardEvent) => { if (e.key === "Escape") close(); };
        window.addEventListener("keydown", onKey);
        return () => window.removeEventListener("keydown", onKey);
    }, [isOpen, isPinned, close]);

    const listRightMarginClass = isPinned ? "mr-[500px]" : ""; // ajusta si cambias widthClass

    const HeaderTitle = React.useMemo(() => {
        if (!item) return "";
        if (typeof title === "function") return title(item);
        return title ?? "";
    }, [item, title]);

    const Preview: PinnedPreviewSheet<T>["Preview"] = React.useCallback(({ children }) => {
        if (!item) return null;

        // Panel anclado: aside estático sin overlay
        if (isPinned) {
            return createPortal(
                <aside
                    aria-label="Vista previa anclada"
                    className={`fixed inset-y-0 right-0 ${widthClass} bg-background border-l z-40`}
                >
                    {children({ item, isPinned: true, close, togglePin })}
                </aside>,
                document.body
            );
        }

        // Panel no anclado: Sheet de shadcn/ui (con overlay y accesibilidad)
        return createPortal(
            <Sheet open={isOpen} onOpenChange={(o) => (o ? setOpen(true) : close())}>
                <SheetContent side="right" className={`${widthClass} p-0`}>
                    {children({ item, isPinned: false, close, togglePin })}
                </SheetContent>
            </Sheet>,
            document.body
        );
    }, [item, isPinned, isOpen, widthClass, close, togglePin]);

    return { isOpen, isPinned, item, open, close, togglePin, listRightMarginClass, Preview };
}