import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useEffect, useCallback, useImperativeHandle, forwardRef } from "react";
import { FileText, Trash2, Loader2, ChevronDown, ChevronUp, Eye, Image as ImageIcon, Download } from "lucide-react";
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, }, ref) => {
    const [documents, setDocuments] = 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 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(() => {
        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) => {
        editContext?.confirm({
            header: "Delete Document",
            message: "Are you sure you want to delete this document?",
            acceptLabel: "Delete",
            accept: async () => {
                try {
                    const result = await deleteDocument(documentId);
                    if (result.success) {
                        setDocuments((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");
                }
            },
            showCancel: true,
        });
    };
    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);
                }
                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, profileId]);
    useImperativeHandle(ref, () => ({
        uploadFiles: handleFileUpload,
    }));
    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 = async () => {
        if (!editContext?.selectMedia)
            return;
        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);
        }
    };
    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;
    };
    // 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 && documents.length === 0) {
        return null;
    }
    return (_jsxs("div", { className: "border-t border-gray-200 bg-gray-50", 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);
                    // Auto-expand when dropping on collapsed panel
                    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-theme-secondary-light border-2 border-theme-secondary border-dashed"
                    : "hover:bg-gray-100"}`, children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FileText, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }), _jsx("span", { className: "text-xs font-normal text-gray-700", children: isDragOver && !isExpanded ? "Drop file to upload" : "Documents" }), loading && (_jsx(Loader2, { className: "h-3 w-3 animate-spin text-gray-400" })), documents.length > 0 && (_jsxs("span", { className: "text-xs text-gray-500", children: ["(", documents.length, ")"] }))] }), isExpanded ? (_jsx(ChevronUp, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 })) : (_jsx(ChevronDown, { className: "h-4 w-4 text-gray-500", strokeWidth: 1 }))] }), isExpanded && (_jsxs("div", { className: `px-4 pb-3 ${enabled ? `border-2 border-dashed ${isDragOver ? "bg-theme-secondary-light border-theme-secondary" : "border-transparent"}` : ""}`, onDragOver: enabled ? handleDragOver : undefined, onDragEnter: enabled ? handleDragOver : undefined, onDragLeave: enabled ? handleDragLeave : undefined, onDrop: enabled ? handleDrop : undefined, children: [error && (_jsx("div", { className: "mb-2 text-xs text-red-600 bg-red-50 p-2 rounded", children: error })), uploading && (_jsx("div", { className: "mb-2 text-xs text-gray-600 bg-gray-100 p-2 rounded", children: "Uploading document..." })), documents.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-2 mb-2 max-h-[40vh] overflow-y-auto", children: documents.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 && (_jsxs("div", { className: "text-xs text-gray-500 mt-2", children: ["Drag & drop documents and images here or", " ", _jsxs("label", { className: "text-theme-secondary cursor-pointer hover:underline", children: ["browse", _jsx("input", { type: "file", className: "hidden", onChange: (e) => {
                                            handleFileUpload(e.target.files);
                                            // Reset the input so the same file can be selected again
                                            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-theme-secondary cursor-pointer hover:underline disabled:opacity-50 disabled:cursor-wait", 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-xs text-gray-500 text-center py-2", children: "Document upload is disabled for this profile." }))] })), _jsx(Dialog, { open: !!viewingDocument, onOpenChange: (open) => !open && setViewingDocument(null), children: _jsxs(DialogContent, { className: "max-w-4xl max-h-[80vh] flex flex-col", children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Extracted Text" }), _jsx(DialogDescription, { children: viewingDocument?.fileName })] }), _jsx("div", { className: "flex-1 overflow-y-auto mt-4", children: viewingDocument?.extractedText ? (_jsx("pre", { className: "whitespace-pre-wrap text-xs text-gray-700 bg-gray-50 p-4 rounded border max-h-[60vh] overflow-y-auto", children: viewingDocument.extractedText })) : (_jsx("div", { className: "text-sm text-gray-500 text-center py-8", children: "No extracted text available for this document." })) })] }) })] }));
});
AgentDocumentList.displayName = "AgentDocumentList";
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: "inline-flex items-center gap-1.5 rounded-full border border-gray-200 bg-white px-2 py-1 text-xs text-gray-700", children: [isImage && thumbnailUrl ? (_jsx("img", { src: thumbnailUrl, alt: document.fileName, className: "h-8 w-8 object-cover rounded border border-gray-200 flex-shrink-0", onError: () => setThumbnailError(true) })) : isImage && loadingThumbnail ? (_jsx(Loader2, { className: "h-6 w-6 animate-spin text-gray-400 flex-shrink-0", strokeWidth: 1 })) : isImage ? (_jsx(ImageIcon, { className: "h-6 w-6 text-gray-500 flex-shrink-0", strokeWidth: 1 })) : (_jsx(FileText, { className: "h-4 w-4 text-gray-500 flex-shrink-0", strokeWidth: 1 })), _jsx("span", { className: "max-w-[200px] truncate", title: `${document.fileName} (${formatFileSize(fileSize)})`, children: document.fileName }), _jsxs("span", { className: "text-gray-400", children: ["(", formatFileSize(fileSize), ")"] }), document.extractedText && (_jsx("button", { onClick: onViewText, className: "ml-0.5 rounded p-0.5 hover:bg-theme-secondary-light text-theme-secondary", "aria-label": "View extracted text", title: "View extracted text", children: _jsx(Eye, { className: "h-3 w-3", strokeWidth: 1 }) })), _jsx("button", { onClick: onDownload, className: "ml-0.5 rounded p-0.5 hover:bg-gray-200", "aria-label": "Download document", title: "Download document", children: _jsx(Download, { className: "h-3 w-3", strokeWidth: 1 }) }), _jsx("button", { onClick: onDelete, className: "ml-0.5 rounded p-0.5 hover:bg-gray-200", "aria-label": "Delete document", title: "Delete document", children: _jsx(Trash2, { className: "h-3 w-3", strokeWidth: 1 }) })] }));
}
//# sourceMappingURL=AgentDocumentList.js.map