import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useEffect, useCallback, useImperativeHandle, forwardRef, } from "react";
import { createPortal } from "react-dom";
import { FileText, Loader2, ChevronDown, ChevronUp, Eye, Image as ImageIcon, Download, Upload, } from "lucide-react";
import { DeleteIcon } from "../../../../components/ui/delete-icon";
import { AGENT_DOCUMENT_UPLOADED_EVENT, AGENT_DOCUMENTS_CHANGED_EVENT, getAgentDocuments, deleteDocument, uploadDocument, downloadDocument, } from "../../../services/agentService";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "../../../../components/ui/dialog";
import { useEditContext } from "../../../client/editContext";
export const AgentDocumentList = forwardRef(({ agentId, maxFileSizeMB = 10, enabled = true, profileId, headerless, onCountChange, loadOnly, headerActionsContainer, composerInline, onRequestClose, }, ref) => {
    const [documents, setDocuments] = useState([]);
    const [stagedDocuments, setStagedDocuments] = useState([]);
    // Start with loading=true to prevent early return before we've loaded documents
    const [loading, setLoading] = useState(true);
    const [uploading, setUploading] = useState(false);
    const [browsingMedia, setBrowsingMedia] = useState(false);
    const [isDragOver, setIsDragOver] = useState(false);
    const [error, setError] = useState(null);
    const [isExpanded, setIsExpanded] = useState(false);
    const [viewingDocument, setViewingDocument] = useState(null);
    const editContext = useEditContext();
    const mergeDocument = useCallback((documentToMerge) => {
        setDocuments((prev) => {
            const existingIndex = prev.findIndex((doc) => doc.id === documentToMerge.id);
            if (existingIndex === -1) {
                return [documentToMerge, ...prev];
            }
            const next = [...prev];
            next[existingIndex] = documentToMerge;
            return next;
        });
    }, []);
    const mergeStagedDocument = useCallback((documentToMerge) => {
        setStagedDocuments((prev) => {
            const existingIndex = prev.findIndex((doc) => doc.id === documentToMerge.id);
            if (existingIndex === -1) {
                return [...prev, documentToMerge];
            }
            const next = [...prev];
            next[existingIndex] = documentToMerge;
            return next;
        });
    }, []);
    const loadDocuments = useCallback(async () => {
        if (!agentId) {
            return;
        }
        try {
            setLoading(true);
            const result = await getAgentDocuments(agentId);
            if (result.success && result.documents) {
                setDocuments(result.documents);
            }
        }
        catch (err) {
            console.error("Failed to load documents", err);
        }
        finally {
            setLoading(false);
        }
    }, [agentId]);
    // Always load documents on mount and when agentId changes
    useEffect(() => {
        if (agentId) {
            loadDocuments();
        }
        else {
            // No agentId, clear loading state
            setLoading(false);
        }
    }, [agentId, loadDocuments]);
    useEffect(() => {
        setStagedDocuments([]);
    }, [agentId, profileId]);
    useEffect(() => {
        onCountChange?.(documents.length);
    }, [documents.length, onCountChange]);
    useEffect(() => {
        const handleDocumentUploaded = (event) => {
            const detail = event
                .detail;
            if (!detail || detail.agentId !== agentId) {
                return;
            }
            mergeDocument(detail.document);
            setIsExpanded(true);
            setError(null);
        };
        window.addEventListener(AGENT_DOCUMENT_UPLOADED_EVENT, handleDocumentUploaded);
        return () => {
            window.removeEventListener(AGENT_DOCUMENT_UPLOADED_EVENT, handleDocumentUploaded);
        };
    }, [agentId, mergeDocument]);
    useEffect(() => {
        const handleDocumentsChanged = (event) => {
            const detail = event
                .detail;
            if (!detail || detail.agentId !== agentId) {
                return;
            }
            setIsExpanded(true);
            setError(null);
            void loadDocuments();
        };
        window.addEventListener(AGENT_DOCUMENTS_CHANGED_EVENT, handleDocumentsChanged);
        return () => {
            window.removeEventListener(AGENT_DOCUMENTS_CHANGED_EVENT, handleDocumentsChanged);
        };
    }, [agentId, loadDocuments]);
    const handleDelete = async (documentId) => {
        try {
            const result = await deleteDocument(documentId);
            if (result.success) {
                setDocuments((prev) => prev.filter((d) => d.id !== documentId));
                setStagedDocuments((prev) => prev.filter((d) => d.id !== documentId));
            }
            else {
                setError(result.error || "Failed to delete document");
            }
        }
        catch (err) {
            console.error("Failed to delete document", err);
            setError("Failed to delete document");
        }
    };
    const handleFileUpload = useCallback(async (files) => {
        if (!files || files.length === 0)
            return;
        // Convert to array for easier processing
        const fileList = Array.from(files);
        const maxSizeBytes = maxFileSizeMB * 1024 * 1024;
        // Auto-expand and clear error when starting upload
        setIsExpanded(true);
        setError(null);
        setUploading(true);
        try {
            for (const file of fileList) {
                if (file.size > maxSizeBytes) {
                    setError(`File "${file.name}" exceeds maximum allowed size of ${maxFileSizeMB} MB`);
                    continue;
                }
                const result = await uploadDocument(agentId, file, profileId);
                if (result.success && result.document) {
                    mergeDocument(result.document);
                    mergeStagedDocument(result.document);
                }
                else {
                    setError(result.error || `Failed to upload "${file.name}"`);
                }
            }
        }
        catch (err) {
            console.error("Failed to upload document", err);
            setError(err.message || "Failed to upload document");
        }
        finally {
            setUploading(false);
        }
    }, [agentId, maxFileSizeMB, mergeDocument, mergeStagedDocument, profileId]);
    const handleDragOver = (e) => {
        e.preventDefault();
        e.stopPropagation();
        if (!isDragOver)
            setIsDragOver(true);
    };
    const handleDragLeave = (e) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragOver(false);
    };
    const handleDrop = (e) => {
        e.preventDefault();
        e.stopPropagation();
        setIsDragOver(false);
        // Only handle file drops, not component/item drops
        if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
            handleFileUpload(e.dataTransfer.files);
        }
    };
    const handlePaste = (e) => {
        if (!enabled)
            return;
        const items = e.clipboardData?.items;
        if (!items)
            return;
        const files = [];
        for (let i = 0; i < items.length; i++) {
            const item = items[i];
            if (!item)
                continue;
            if (item.type.indexOf("image") !== -1 || item.kind === "file") {
                const file = item.getAsFile();
                if (file) {
                    // If it's a pasted image, it might not have a useful name
                    if (file.name === "image.png" &&
                        item.type.indexOf("image") !== -1) {
                        // Generate a better name for pasted images
                        const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
                        const extension = item.type.split("/")[1] || "png";
                        const newFile = new File([file], `pasted-image-${timestamp}.${extension}`, { type: file.type });
                        files.push(newFile);
                    }
                    else {
                        files.push(file);
                    }
                }
            }
        }
        if (files.length > 0) {
            handleFileUpload(files);
        }
    };
    const handleBrowseMedia = useCallback(async () => {
        if (!editContext?.selectMedia)
            return;
        // Close the containing popover so the media library modal isn't
        // hidden behind it (z-order conflict).
        onRequestClose?.();
        setBrowsingMedia(true);
        setError(null);
        try {
            // Open media selector - returns media item ID/path
            const mediaId = await editContext.selectMedia({
                selectedIdPath: "",
                mode: "images",
            });
            if (!mediaId) {
                // User cancelled
                setBrowsingMedia(false);
                return;
            }
            // Auto-expand when adding media
            setIsExpanded(true);
            // Fetch media URL from server
            const urlResponse = await fetch(`/parhelia/agent/GetMediaUrl?itemId=${encodeURIComponent(mediaId)}`);
            if (!urlResponse.ok)
                throw new Error("Failed to get media URL");
            const { url, alt } = await urlResponse.json();
            // Fetch the actual image blob
            const imageResponse = await fetch(url);
            if (!imageResponse.ok)
                throw new Error("Failed to fetch image");
            const blob = await imageResponse.blob();
            // Create a File object with appropriate name
            // Extract filename from mediaId path (e.g., "/sitecore/media library/images/photo" -> "photo")
            const pathParts = mediaId.split("/");
            const rawName = pathParts[pathParts.length - 1] || "media-image";
            // Clean the name for use as filename
            const cleanName = rawName.replace(/[^a-zA-Z0-9_-]/g, "_");
            const extension = blob.type.split("/")[1] || "jpg";
            const file = new File([blob], `${cleanName}.${extension}`, {
                type: blob.type,
            });
            // Upload to agent document store
            await handleFileUpload([file]);
        }
        catch (err) {
            console.error("Failed to add media library image", err);
            setError("Failed to add image from media library");
        }
        finally {
            setBrowsingMedia(false);
        }
    }, [editContext, onRequestClose, handleFileUpload]);
    useImperativeHandle(ref, () => ({
        uploadFiles: handleFileUpload,
        browseMedia: handleBrowseMedia,
        getStagedAttachments: () => stagedDocuments.map(agentDocumentToMessageAttachment),
        clearStagedAttachments: () => setStagedDocuments([]),
    }), [handleFileUpload, handleBrowseMedia, stagedDocuments]);
    const formatFileSize = (bytes) => {
        if (bytes < 1024)
            return `${bytes} B`;
        if (bytes < 1024 * 1024)
            return `${(bytes / 1024).toFixed(1)} KB`;
        return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
    };
    const isImageFile = (fileName, contentType) => {
        if (!fileName)
            return false;
        const extension = fileName.toLowerCase().split(".").pop();
        const imageExtensions = ["png", "jpg", "jpeg", "gif", "webp"];
        if (imageExtensions.includes(extension || ""))
            return true;
        if (contentType?.toLowerCase().startsWith("image/"))
            return true;
        return false;
    };
    // Offscreen mount that just feeds the count badge.
    if (loadOnly) {
        return null;
    }
    // The composer owns the surrounding drop zone; only paint staged state here.
    const visibleDocuments = composerInline ? stagedDocuments : documents;
    if (composerInline &&
        visibleDocuments.length === 0 &&
        !uploading &&
        !error) {
        return null;
    }
    // Show section if we have documents OR if upload is enabled.
    // Hide during the initial load too — otherwise the tray flashes in and out
    // when switching to an agent that has no documents and disabled uploads.
    if (!enabled && visibleDocuments.length === 0) {
        return null;
    }
    const fileBrowseInput = enabled ? (_jsxs("label", { className: "text-highlight-100 badge-pad-sm hover:bg-neutral-grey-5 inline-flex cursor-pointer items-center gap-1 rounded text-[10px]", title: "Upload documents", children: [_jsx(Upload, { className: "h-3 w-3", strokeWidth: 1.5 }), "browse", _jsx("input", { type: "file", className: "hidden", onChange: (e) => {
                    handleFileUpload(e.target.files);
                    e.target.value = "";
                }, accept: ".txt,.md,.pdf,.docx,.xlsx,.pptx,.csv,.json,.xml,.cs,.js,.ts,.tsx,.jsx,.py,.java,.cpp,.c,.h,.hpp,.cshtml,.razor,.vb,.php,.rb,.go,.rs,.swift,.kt,.scala,.sql,.sh,.ps1,.bat,.yaml,.yml,.png,.jpg,.jpeg,.gif,.webp" })] })) : null;
    const mediaLibraryButton = enabled && editContext?.selectMedia ? (_jsxs("button", { type: "button", onClick: handleBrowseMedia, disabled: browsingMedia, className: "text-highlight-100 badge-pad-sm hover:bg-neutral-grey-5 inline-flex items-center gap-1 rounded text-[10px] disabled:cursor-wait disabled:opacity-50", title: "Pick from media library", children: [browsingMedia ? (_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1.5 })) : (_jsx(ImageIcon, { className: "h-3 w-3", strokeWidth: 1.5 })), "media library"] })) : null;
    const headerActionsContent = fileBrowseInput || mediaLibraryButton ? (_jsxs("div", { className: "flex items-center gap-1", children: [fileBrowseInput, mediaLibraryButton] })) : null;
    const useHeaderPortal = headerless && headerActionsContainer;
    const bodyContent = (_jsxs("div", { className: `${composerInline ? "px-3 pt-0 pb-3" : `px-4 ${headerless ? "pt-3" : ""} pb-3`} ${enabled && !composerInline
            ? `border-2 border-dashed ${isDragOver
                ? "bg-highlight-10 border-highlight-100"
                : "border-transparent"}`
            : ""}`, onDragOver: enabled ? handleDragOver : undefined, onDragEnter: enabled ? handleDragOver : undefined, onDragLeave: enabled ? handleDragLeave : undefined, onDrop: enabled ? handleDrop : undefined, children: [useHeaderPortal && headerActionsContent
                ? createPortal(headerActionsContent, headerActionsContainer)
                : null, headerless &&
                !composerInline &&
                !useHeaderPortal &&
                headerActionsContent && (_jsx("div", { className: "mb-2 flex items-center justify-end", children: headerActionsContent })), error && (_jsx("div", { className: "text-feedback-red bg-feedback-red-light mb-2 rounded p-2 text-xs", children: error })), uploading && (_jsxs("div", { className: "bg-neutral-grey-5 text-neutral-grey-50 mb-2 flex items-center gap-2 rounded p-2 text-xs", children: [_jsx(Loader2, { className: "text-neutral-grey-50 h-3 w-3 animate-spin", strokeWidth: 1 }), _jsx("span", { children: "Uploading document..." })] })), visibleDocuments.length > 0 && (_jsx("div", { className: `${composerInline ? "pr-1 pb-8" : "mb-2"} flex max-h-[40vh] flex-wrap gap-2 overflow-y-auto`, "data-testid": "agent-composer-documents", children: visibleDocuments.map((doc) => {
                    const fileSize = doc.fileSize ?? 0;
                    const isImage = isImageFile(doc.fileName, doc.contentType);
                    return (_jsx(DocumentThumbnail, { document: doc, fileSize: fileSize, isImage: isImage, onViewText: () => doc.extractedText && setViewingDocument(doc), onDelete: () => handleDelete(doc.id), onDownload: () => {
                            downloadDocument(doc.id)
                                .then((blob) => {
                                const url = URL.createObjectURL(blob);
                                const a = document.createElement("a");
                                a.href = url;
                                a.download = doc.fileName;
                                document.body.appendChild(a);
                                a.click();
                                document.body.removeChild(a);
                                URL.revokeObjectURL(url);
                            })
                                .catch((err) => {
                                console.error("Failed to download document", err);
                            });
                        }, formatFileSize: formatFileSize }, doc.id));
                }) })), enabled && headerless && !composerInline && (_jsxs("div", { className: "text-neutral-grey-50 mt-2 text-xs", children: ["Drag & drop documents and images here", maxFileSizeMB ? ` (max ${maxFileSizeMB} MB)` : ""] })), enabled && !headerless && (_jsxs("div", { className: "text-neutral-grey-50 mt-2 text-xs", children: ["Drag & drop documents and images here or", " ", _jsxs("label", { className: "text-highlight-100 cursor-pointer hover:underline", children: ["browse", _jsx("input", { type: "file", className: "hidden", onChange: (e) => {
                                    handleFileUpload(e.target.files);
                                    e.target.value = "";
                                }, accept: ".txt,.md,.pdf,.docx,.xlsx,.pptx,.csv,.json,.xml,.cs,.js,.ts,.tsx,.jsx,.py,.java,.cpp,.c,.h,.hpp,.cshtml,.razor,.vb,.php,.rb,.go,.rs,.swift,.kt,.scala,.sql,.sh,.ps1,.bat,.yaml,.yml,.png,.jpg,.jpeg,.gif,.webp" })] }), editContext?.selectMedia && (_jsxs(_Fragment, { children: [" or ", _jsx("button", { onClick: handleBrowseMedia, disabled: browsingMedia, className: "text-highlight-100 cursor-pointer hover:underline disabled:cursor-wait disabled:opacity-50", type: "button", children: browsingMedia ? (_jsxs("span", { className: "inline-flex items-center gap-1", children: [_jsx(Loader2, { className: "h-3 w-3 animate-spin", strokeWidth: 1 }), "loading..."] })) : ("media library") })] })), maxFileSizeMB && ` (max ${maxFileSizeMB} MB)`] })), !enabled && documents.length === 0 && !loading && (_jsx("div", { className: "text-neutral-grey-50 py-2 text-center text-xs", children: "Document upload is disabled for this profile." }))] }));
    const dialog = (_jsx(Dialog, { open: !!viewingDocument, onOpenChange: (open) => !open && setViewingDocument(null), children: _jsxs(DialogContent, { className: "flex max-h-[80vh] max-w-4xl flex-col", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Extracted Text" }), _jsx(DialogDescription, { children: viewingDocument?.fileName })] }), _jsx("div", { className: "mt-4 flex-1 overflow-y-auto", children: viewingDocument?.extractedText ? (_jsx("pre", { className: "text-neutral-grey-100 bg-neutral-grey-5 max-h-[60vh] overflow-y-auto rounded border p-4 text-xs whitespace-pre-wrap", children: viewingDocument.extractedText })) : (_jsx("div", { className: "text-neutral-grey-50 py-8 text-center text-sm", children: "No extracted text available for this document." })) })] }) }));
    if (headerless) {
        return (_jsxs("div", { className: composerInline ? "bg-neutral-grey-5" : "bg-neutral-grey-5", onPaste: handlePaste, children: [bodyContent, dialog] }));
    }
    return (_jsxs("div", { className: "border-border-default bg-neutral-grey-5 border-t", onPaste: handlePaste, children: [_jsxs("button", { onClick: () => setIsExpanded(!isExpanded), onDragOver: enabled ? handleDragOver : undefined, onDragEnter: enabled ? handleDragOver : undefined, onDragLeave: enabled ? handleDragLeave : undefined, onDrop: enabled
                    ? (e) => {
                        handleDrop(e);
                        if (!isExpanded) {
                            setIsExpanded(true);
                        }
                    }
                    : undefined, className: `flex w-full cursor-pointer items-center justify-between px-4 py-2 text-left transition-colors ${isDragOver && !isExpanded
                    ? "bg-highlight-10 border-highlight-100 border-2 border-dashed"
                    : "hover:bg-neutral-grey-5"}`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileText, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1 }), _jsx("span", { className: "text-neutral-grey-100 text-xs font-normal", children: isDragOver && !isExpanded ? "Drop file to upload" : "Documents" }), loading && (_jsx(Loader2, { className: "text-neutral-grey-50 h-3 w-3 animate-spin" })), documents.length > 0 && (_jsxs("span", { className: "text-neutral-grey-50 text-xs", children: ["(", documents.length, ")"] }))] }), isExpanded ? (_jsx(ChevronUp, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1 })) : (_jsx(ChevronDown, { className: "text-neutral-grey-50 h-4 w-4", strokeWidth: 1 }))] }), isExpanded && bodyContent, dialog] }));
});
AgentDocumentList.displayName = "AgentDocumentList";
function agentDocumentToMessageAttachment(document) {
    return {
        id: document.id,
        agentId: document.agentId,
        fileName: document.fileName,
        fileSize: document.fileSize,
        contentType: document.contentType,
        uploadedBy: document.uploadedBy,
        uploadedDate: document.uploadedDate,
    };
}
function DocumentThumbnail({ document, fileSize, isImage, onViewText, onDelete, onDownload, formatFileSize, }) {
    const [thumbnailUrl, setThumbnailUrl] = useState(null);
    const [loadingThumbnail, setLoadingThumbnail] = useState(false);
    const [thumbnailError, setThumbnailError] = useState(false);
    useEffect(() => {
        if (!isImage || thumbnailUrl || loadingThumbnail || thumbnailError)
            return;
        const loadThumbnail = async () => {
            try {
                setLoadingThumbnail(true);
                const blob = await downloadDocument(document.id);
                const url = URL.createObjectURL(blob);
                setThumbnailUrl(url);
            }
            catch (err) {
                console.error("Failed to load thumbnail", err);
                setThumbnailError(true);
            }
            finally {
                setLoadingThumbnail(false);
            }
        };
        loadThumbnail();
        // Cleanup object URL on unmount
        return () => {
            if (thumbnailUrl) {
                URL.revokeObjectURL(thumbnailUrl);
            }
        };
    }, [isImage, document.id, thumbnailUrl, loadingThumbnail, thumbnailError]);
    return (_jsxs("span", { className: "border-border-default text-neutral-grey-100 inline-grid max-w-full grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-x-2 rounded-md border bg-white px-2 py-1.5 text-[12px] shadow-sm", children: [isImage && thumbnailUrl ? (_jsx("img", { src: thumbnailUrl, alt: document.fileName, className: "border-border-default row-span-2 h-8 w-8 flex-shrink-0 rounded border object-cover", onError: () => setThumbnailError(true) })) : isImage && loadingThumbnail ? (_jsx(Loader2, { className: "text-neutral-grey-50 row-span-2 h-8 w-8 flex-shrink-0 animate-spin", strokeWidth: 1 })) : isImage ? (_jsx(ImageIcon, { className: "text-neutral-grey-50 row-span-2 h-8 w-8 flex-shrink-0", strokeWidth: 1 })) : (_jsx(FileText, { className: "text-neutral-grey-50 bg-neutral-grey-5 row-span-2 h-8 w-8 flex-shrink-0 rounded border p-1.5", strokeWidth: 1 })), _jsx("span", { className: "max-w-[260px] truncate leading-tight font-medium", title: `${document.fileName} (${formatFileSize(fileSize)})`, children: document.fileName }), _jsx("span", { className: "text-neutral-grey-50 col-start-2 text-[11px] leading-tight", children: isImage ? "Image" : formatFileSize(fileSize) }), _jsxs("span", { className: "row-span-2 flex items-center gap-0.5", children: [document.extractedText && (_jsx("button", { onClick: onViewText, className: "hover:bg-highlight-10 text-highlight-100 rounded p-1", "aria-label": "View extracted text", title: "View extracted text", children: _jsx(Eye, { className: "h-3.5 w-3.5", strokeWidth: 1 }) })), _jsx("button", { onClick: onDownload, className: "hover:bg-neutral-grey-10 rounded p-1", "aria-label": "Download document", title: "Download document", children: _jsx(Download, { className: "h-3.5 w-3.5", strokeWidth: 1 }) }), _jsx("button", { onClick: onDelete, className: "hover:bg-neutral-grey-10 rounded p-1", "aria-label": "Delete document", title: "Delete document", children: _jsx(DeleteIcon, { size: "sm" }) })] })] }));
}
//# sourceMappingURL=AgentDocumentList.js.map