import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useState, useRef, useMemo, useCallback, memo, } from "react";
import { cn } from "../../lib/utils";
import { Button } from "../../components/ui/button";
import { Grid3X3, Square, List, Upload, RefreshCw, Loader2, FileIcon, } from "lucide-react";
import { useEditContext } from "../client/editContext";
import { getChildren } from "../services/contentService";
import { toast } from "sonner";
import { FilterInput } from "../../components/FilterInput";
import { executeSearch } from "../services/searchService";
import { useDebouncedCallback } from "use-debounce";
import { Spinner } from "../ui/Spinner";
// Memoized thumbnail item component to prevent unnecessary re-renders
const ThumbnailItem = memo(({ thumbnail, isSelected, onClick, viewMode, }) => {
    const hasImage = !!thumbnail.thumbUrl;
    const iconSrc = thumbnail.largeIcon || thumbnail.icon;
    if (viewMode === "list") {
        return (_jsxs("div", { className: cn(isSelected
                ? "border-blue-300 bg-blue-100"
                : "bg-white hover:bg-gray-50", "flex cursor-pointer items-center gap-3 rounded-lg border p-3 transition-colors duration-200"), onClick: onClick, children: [_jsx("div", { className: "flex h-16 w-16 flex-shrink-0 items-center justify-center rounded-md bg-gray-50", children: hasImage ? (_jsx("img", { src: thumbnail.thumbUrl, alt: thumbnail.name, className: "max-h-full max-w-full object-contain" })) : iconSrc ? (_jsx("img", { src: iconSrc, alt: thumbnail.name, className: "object-contain opacity-80", style: { width: "32px", height: "32px" } })) : (_jsx(FileIcon, { className: "h-8 w-8 text-gray-400" })) }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-dark truncate text-xs font-medium", children: thumbnail.name }), _jsx("div", { className: "mt-1 text-xs text-gray-500", children: "Media File" })] })] }));
    }
    const isLarge = viewMode === "large-grid";
    const gridSrc = isLarge ? thumbnail.previewUrl : thumbnail.thumbUrl;
    return (_jsxs("div", { className: cn(isSelected
            ? "shadow-lg ring-2 ring-blue-500"
            : "shadow-sm hover:shadow-md", "cursor-pointer overflow-hidden rounded-lg bg-white transition-all duration-200 hover:scale-105"), onClick: onClick, children: [_jsx("div", { className: "flex aspect-square items-center justify-center bg-gray-50", children: gridSrc ? (_jsx("img", { src: gridSrc, alt: thumbnail.name, className: "max-h-full max-w-full object-contain" })) : iconSrc ? (_jsx("img", { src: iconSrc, alt: thumbnail.name, className: "object-contain opacity-80", style: { width: "32px", height: "32px" } })) : (_jsx(FileIcon, { className: cn("text-gray-400", isLarge ? "h-20 w-20" : "h-12 w-12") })) }), _jsx("div", { className: isLarge ? "p-3" : "p-2", children: _jsx("div", { className: cn("line-clamp-2 break-all text-gray-700", isLarge ? "text-sm font-medium" : "text-xs font-medium"), children: thumbnail.name }) })] }));
});
ThumbnailItem.displayName = "ThumbnailItem";
export function MediaFolderBrowser({ folderId, language = "en", onMediaSelected, }) {
    const [viewMode, setViewMode] = useState("grid");
    const [images, setImages] = useState([]);
    const [selectedImage, setSelectedImage] = useState();
    const selectedImageRef = useRef(selectedImage);
    const [loading, setLoading] = useState(false);
    const [uploading, setUploading] = useState(false);
    const [searchQuery, setSearchQuery] = useState("");
    const [searchResults, setSearchResults] = useState([]);
    const [searching, setSearching] = useState(false);
    const editContext = useEditContext();
    // Keep ref in sync with state
    useEffect(() => {
        selectedImageRef.current = selectedImage;
    }, [selectedImage]);
    useEffect(() => {
        loadMediaFiles();
    }, [folderId]);
    const loadMediaFiles = async () => {
        if (!editContext || !folderId)
            return;
        setLoading(true);
        try {
            const children = await getChildren(folderId, editContext.sessionId, [], false, language);
            setImages(children || []);
        }
        catch (error) {
            console.error("Error loading media files:", error);
            setImages([]);
        }
        finally {
            setLoading(false);
        }
    };
    const handleSearch = useDebouncedCallback(async (query) => {
        if (!editContext || !folderId || !query.trim()) {
            setSearchResults([]);
            setSearching(false);
            return;
        }
        setSearching(true);
        try {
            const result = await executeSearch({
                index: "master",
                query: query.trim(),
                editContext,
                rootItemIds: [folderId],
                maxResults: 50,
            });
            if (result.type === "success") {
                // Transform search results to Thumbnail format
                // No template filtering needed since search is scoped to media folder
                const thumbnails = result.data.map((item) => ({
                    id: item.id,
                    name: item.name,
                    thumbUrl: item.thumbUrl || "",
                    previewUrl: item.previewUrl || item.thumbUrl || "",
                    icon: item.icon || "",
                    largeIcon: item.largeIcon || "",
                }));
                setSearchResults(thumbnails);
            }
            else {
                setSearchResults([]);
                toast.error("Search failed. Please try again.");
            }
        }
        catch (error) {
            console.error("Error searching media files:", error);
            setSearchResults([]);
            toast.error("Error searching media files");
        }
        finally {
            setSearching(false);
        }
    }, 600);
    useEffect(() => {
        if (searchQuery.trim()) {
            handleSearch(searchQuery);
        }
        else {
            setSearchResults([]);
        }
    }, [searchQuery]);
    const handleClick = useCallback(async (thumbnail, ev) => {
        // Set selected image immediately and update ref - set synchronously for immediate visual feedback
        selectedImageRef.current = thumbnail;
        setSelectedImage(thumbnail);
        // Open the media item in the slot next to the active one (or create new if no next slot exists)
        if (editContext) {
            // Check if thumbnail has language/version (from ItemTreeNodeData) or use defaults
            const itemLanguage = thumbnail.language || language;
            const itemVersion = thumbnail.version ?? 0;
            const slots = editContext.editorSlots;
            const activeSlotId = editContext.activeSlotId;
            // If the user clicked inside a non-active slot, `activeSlotId` may still point
            // to a different slot. Infer the host slot from the DOM and treat that as the base.
            const hostSlotId = ev.currentTarget
                .closest('[data-editor-slot="true"]')
                ?.getAttribute("data-slotid") ?? null;
            const baseSlotId = hostSlotId || activeSlotId;
            // Proactively activate the host slot so follow-up UI actions behave consistently.
            if (hostSlotId && hostSlotId !== activeSlotId) {
                editContext.setActiveSlot(hostSlotId);
            }
            // Check if item is already open in any slot - if so, switch to that slot instead of opening a new one
            const existingSlot = slots.find(s => s.itemDescriptor.id === thumbnail.id &&
                s.itemDescriptor.language === itemLanguage &&
                s.itemDescriptor.version === itemVersion);
            if (existingSlot) {
                // Item is already open - just switch to that slot
                editContext.setActiveSlot(existingSlot.slotId);
                // Ensure selectedImage is still set
                if (selectedImageRef.current?.id !== thumbnail.id) {
                    setSelectedImage(thumbnail);
                    selectedImageRef.current = thumbnail;
                }
                return;
            }
            // Find the slot next to the active one
            let nextSlotId = null;
            if (baseSlotId && slots.length > 0) {
                const baseIndex = slots.findIndex((s) => s.slotId === baseSlotId);
                if (baseIndex !== -1 && baseIndex < slots.length - 1) {
                    // There's a slot to the right of the clicked (or active) one
                    nextSlotId = slots[baseIndex + 1]?.slotId ?? null;
                }
            }
            // Use setTimeout to defer loadItem slightly, allowing selection to render first
            await new Promise((resolve) => setTimeout(resolve, 0));
            await editContext.loadItem({
                id: thumbnail.id,
                language: itemLanguage,
                version: itemVersion,
            }, nextSlotId
                ? {
                    targetSlotId: nextSlotId,
                }
                : {
                    openInNewSlot: true,
                });
            // Ensure selectedImage is still set after loadItem (in case re-render reset it)
            if (selectedImageRef.current?.id !== thumbnail.id) {
                setSelectedImage(thumbnail);
                selectedImageRef.current = thumbnail;
            }
        }
    }, [editContext, language]);
    const handleUpload = async () => {
        if (!folderId)
            return;
        const fileInput = document.createElement("input");
        fileInput.type = "file";
        fileInput.multiple = true;
        fileInput.accept = "*/*";
        fileInput.onchange = async (e) => {
            const files = Array.from(e.target.files || []);
            if (files.length > 0) {
                await uploadFiles(files);
            }
        };
        fileInput.click();
    };
    const uploadFiles = async (files) => {
        const formData = new FormData();
        files.forEach((file, index) => {
            formData.append("file" + index, file);
        });
        try {
            setUploading(true);
            const response = await fetch("/parhelia/upload?folder=" + folderId, {
                method: "POST",
                body: formData,
            });
            if (!response.ok) {
                throw new Error("Upload failed");
            }
            // Reload media files after successful upload
            await loadMediaFiles();
        }
        catch (error) {
            console.error("Error uploading files:", error);
            if (editContext) {
                toast.error("Failed to upload files. Please try again.");
            }
        }
        finally {
            setUploading(false);
        }
    };
    const displayImages = useMemo(() => {
        return searchQuery.trim() ? searchResults : images;
    }, [searchQuery, searchResults, images]);
    // Create stable click handlers map to prevent ThumbnailItem re-renders
    const clickHandlers = useMemo(() => {
        const handlers = new Map();
        displayImages.forEach((t) => {
            handlers.set(t.id, (ev) => void handleClick(t, ev));
        });
        return handlers;
    }, [displayImages, handleClick]);
    const GridView = useMemo(() => {
        return (_jsx("div", { className: "grid gap-3 p-4", style: {
                gridTemplateColumns: "repeat(auto-fill, minmax(160px, 1fr))",
            }, children: displayImages.map((t) => (_jsx(ThumbnailItem, { thumbnail: t, isSelected: selectedImage?.id === t.id, onClick: clickHandlers.get(t.id) || (() => undefined), viewMode: "grid" }, t.id))) }));
    }, [displayImages, selectedImage, clickHandlers]);
    const LargeGridView = useMemo(() => {
        return (_jsx("div", { className: "grid gap-4 p-4", style: {
                gridTemplateColumns: "repeat(auto-fill, minmax(240px, 1fr))",
            }, children: displayImages.map((t) => (_jsx(ThumbnailItem, { thumbnail: t, isSelected: selectedImage?.id === t.id, onClick: clickHandlers.get(t.id) || (() => undefined), viewMode: "large-grid" }, t.id))) }));
    }, [displayImages, selectedImage, clickHandlers]);
    const ListView = useMemo(() => {
        return (_jsx("div", { className: "flex flex-col gap-1 p-2", children: displayImages.map((t) => (_jsx(ThumbnailItem, { thumbnail: t, isSelected: selectedImage?.id === t.id, onClick: clickHandlers.get(t.id) || (() => undefined), viewMode: "list" }, t.id))) }));
    }, [displayImages, selectedImage, clickHandlers]);
    const renderContent = useMemo(() => {
        const isDisplayingSearch = searchQuery.trim();
        const currentLoading = isDisplayingSearch ? searching : loading;
        if (currentLoading) {
            return (_jsx("div", { className: "flex h-64 items-center justify-center", children: _jsx(Loader2, { className: "h-8 w-8 animate-spin" }) }));
        }
        if (displayImages.length === 0) {
            return (_jsxs("div", { className: "flex h-64 flex-col items-center justify-center text-gray-500", children: [_jsx("div", { className: "mb-4 text-4xl", children: isDisplayingSearch ? "🔍" : "📁" }), _jsx("div", { className: "text-lg font-medium", children: isDisplayingSearch ? "No results found" : "No media files found" }), _jsx("div", { className: "text-sm", children: isDisplayingSearch
                            ? "Try a different search term"
                            : "Upload some media files to get started" })] }));
        }
        switch (viewMode) {
            case "grid":
                return GridView;
            case "large-grid":
                return LargeGridView;
            case "list":
                return ListView;
            default:
                return GridView;
        }
    }, [viewMode, displayImages, searchQuery, searching, loading, GridView, LargeGridView, ListView]);
    return (_jsxs("div", { className: "relative flex h-full flex-col", children: [uploading && (_jsxs("div", { className: "absolute inset-0 z-10 flex items-center justify-center gap-2 bg-white/50 backdrop-blur-[1px]", children: [_jsx(Spinner, { size: "3xl" }), _jsx("span", { className: "text-sm font-medium text-gray-500", children: "Uploading media..." })] })), _jsxs("div", { className: "flex items-center justify-between border-b bg-gray-50 px-4 py-2", children: [_jsxs("div", { className: "text-xs font-medium text-gray-700", children: [searchQuery.trim() ? searchResults.length : images.length, " media file", (searchQuery.trim() ? searchResults.length : images.length) !== 1
                                ? "s"
                                : "", searchQuery.trim() && " found"] }), _jsxs("div", { className: "flex gap-1", children: [_jsx(Button, { size: "sm", variant: viewMode === "grid" ? "outline" : "default", onClick: () => setViewMode("grid"), title: "Grid View", className: "p-1", children: _jsx(Grid3X3, { className: "h-4 w-4" }) }), _jsx(Button, { size: "sm", variant: viewMode === "large-grid" ? "outline" : "default", onClick: () => setViewMode("large-grid"), title: "Large Grid View", className: "p-1", children: _jsx(Square, { className: "h-4 w-4" }) }), _jsx(Button, { size: "sm", variant: viewMode === "list" ? "outline" : "default", onClick: () => setViewMode("list"), title: "List View", className: "p-1", children: _jsx(List, { className: "h-4 w-4" }) }), _jsx(Button, { size: "sm", onClick: handleUpload, disabled: uploading || !folderId, title: "Upload Files", className: "ml-2 p-1", children: _jsx(Upload, { className: "h-4 w-4" }) }), _jsx(Button, { size: "sm", onClick: loadMediaFiles, title: "Refresh", className: "ml-1 p-1", children: _jsx(RefreshCw, { className: "h-4 w-4" }) })] })] }), _jsx("div", { className: "border-b bg-white px-4 py-2", children: _jsx(FilterInput, { value: searchQuery, onChange: setSearchQuery, placeholder: "Search media files...", loading: searching, onClear: () => setSearchQuery("") }) }), _jsx("div", { className: "min-h-0 flex-1 overflow-x-hidden overflow-y-auto", style: {
                    scrollbarWidth: "thin",
                    scrollbarColor: "#9CA3AF #F3F4F6",
                }, children: renderContent }), selectedImage && (_jsxs("div", { className: "border-t bg-gray-50 p-3", children: [_jsxs("div", { className: "text-dark truncate text-xs font-medium", children: ["Selected: ", selectedImage.name] }), _jsx("div", { className: "mt-1 text-xs text-gray-500", children: "Click to select media item" })] }))] }));
}
//# sourceMappingURL=MediaFolderBrowser.js.map