import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect, useState, memo } from "react";
import { useUserSession } from "@vertesia/ui/session";
import { Button, ResizableHandle, ResizablePanel, ResizablePanelGroup, Spinner, useToast } from "@vertesia/ui/core";
import { JSONDisplay, MarkdownRenderer } from "@vertesia/ui/widgets";
import { ContentNature, ImageRenditionFormat, POSTER_RENDITION_NAME } from "@vertesia/common";
import { Copy, Download, SquarePen, AlertTriangle } from "lucide-react";
import { PropertiesEditorModal } from "./PropertiesEditorModal";
import { NavLink } from "@vertesia/ui/router";
// Maximum text size before cropping (128K characters)
const MAX_TEXT_DISPLAY_SIZE = 128 * 1024;
var PanelView;
(function (PanelView) {
    PanelView["Text"] = "text";
    PanelView["Image"] = "image";
    PanelView["Video"] = "video";
})(PanelView || (PanelView = {}));
export function ContentOverview({ object, loadText, refetch, }) {
    const toast = useToast();
    const handleCopyContent = async (content, type) => {
        try {
            await navigator.clipboard.writeText(content);
            toast({
                status: "success",
                title: `${type === "text" ? "Content" : "Properties"} copied`,
                description: `Successfully copied ${type} to clipboard`,
                duration: 2000,
            });
        }
        catch (err) {
            console.error(`Failed to copy ${type}:`, err);
            toast({
                status: "error",
                title: "Copy failed",
                description: `Failed to copy ${type} to clipboard`,
                duration: 5000,
            });
        }
    };
    return (_jsx(_Fragment, { children: _jsxs(ResizablePanelGroup, { direction: "horizontal", className: "h-[calc(100vh-200px)]", children: [_jsx(ResizablePanel, { className: "min-w-[100px]", children: _jsx(PropertiesPanel, { object: object, refetch: refetch ?? (() => Promise.resolve()), handleCopyContent: handleCopyContent }) }), _jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { className: "min-w-[100px]", children: _jsx(DataPanel, { object: object, loadText: loadText ?? false, handleCopyContent: handleCopyContent }) })] }) }));
}
function PropertiesPanel({ object, refetch, handleCopyContent }) {
    const [viewCode, setViewCode] = useState(false);
    const [isPropertiesModalOpen, setPropertiesModalOpen] = useState(false);
    const handleOpenPropertiesModal = () => {
        setPropertiesModalOpen(true);
    };
    const handleClosePropertiesModal = () => {
        setPropertiesModalOpen(false);
    };
    return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex justify-between items-center px-2", children: [_jsxs("div", { className: "flex items-center gap-1 bg-muted mb-2 p-1 rounded", children: [_jsx(Button, { variant: `${viewCode ? "ghost" : "primary"}`, size: "sm", alt: "Preview properties", onClick: () => setViewCode(!viewCode), children: "Properties" }), _jsx(Button, { variant: `${viewCode ? "primary" : "ghost"}`, size: "sm", alt: "View in JSON format", onClick: () => setViewCode(!viewCode), children: "JSON" })] }), _jsxs("div", { className: "flex items-center gap-2", children: [object.properties && (_jsx(Button, { variant: "ghost", size: "sm", title: "Copy properties", onClick: () => handleCopyContent(JSON.stringify(object.properties, null, 2), "properties"), children: _jsx(Copy, { className: "size-4" }) })), _jsx(Button, { variant: "ghost", size: "sm", onClick: handleOpenPropertiesModal, title: "Edit properties", className: "flex items-center gap-2", children: _jsx(SquarePen, { className: "size-4" }) })] })] }), object.properties ? (_jsx("div", { className: "h-[calc(100vh-220px)] overflow-auto px-2", children: _jsx(JSONDisplay, { value: object.properties, viewCode: viewCode }) })) : (_jsx("div", { className: "h-[calc(100vh-220px)] overflow-auto px-2", children: _jsx("div", { children: "No properties defined" }) })), _jsx(PropertiesEditorModal, { isOpen: isPropertiesModalOpen, onClose: handleClosePropertiesModal, object: object, refetch: refetch })] }));
}
function DataPanel({ object, loadText, handleCopyContent }) {
    const { store } = useUserSession();
    const isImage = object?.metadata?.type === ContentNature.Image;
    const isVideo = object?.metadata?.type === ContentNature.Video;
    // Determine initial panel view
    const getInitialView = () => {
        if (isVideo)
            return PanelView.Video;
        if (isImage)
            return PanelView.Image;
        return PanelView.Text;
    };
    const [currentPanel, setCurrentPanel] = useState(getInitialView());
    const [text, setText] = useState(object.text);
    const [isLoadingText, setIsLoadingText] = useState(false);
    const [isTextCropped, setIsTextCropped] = useState(false);
    useEffect(() => {
        if (loadText && !text) {
            setIsLoadingText(true);
            store.objects
                .getObjectText(object.id)
                .then((res) => {
                if (res.text.length > MAX_TEXT_DISPLAY_SIZE) {
                    // Crop the text to 128K characters
                    const croppedText = res.text.substring(0, MAX_TEXT_DISPLAY_SIZE);
                    setText(croppedText);
                    setIsTextCropped(true);
                }
                else {
                    setText(res.text);
                    setIsTextCropped(false);
                }
            })
                .catch((err) => {
                console.error("Failed to load text", err);
            })
                .finally(() => {
                setIsLoadingText(false);
            });
        }
    }, [loadText]);
    return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex justify-between items-center px-2", children: [_jsxs("div", { className: "flex items-center gap-1 bg-muted mb-2 p-1 rounded", children: [isImage &&
                                _jsx(Button, { variant: currentPanel === PanelView.Image ? "primary" : "ghost", size: "sm", alt: "View Image", onClick: () => setCurrentPanel(PanelView.Image), children: "Image" }), isVideo &&
                                _jsx(Button, { variant: currentPanel === PanelView.Video ? "primary" : "ghost", size: "sm", alt: "View Video", onClick: () => setCurrentPanel(PanelView.Video), children: "Video" }), _jsx(Button, { variant: currentPanel === PanelView.Text ? "primary" : "ghost", size: "sm", alt: "View Text", onClick: () => setCurrentPanel(PanelView.Text), children: "Text" })] }), currentPanel === PanelView.Text && _jsx(TextActions, { object: object, text: text, handleCopyContent: handleCopyContent })] }), currentPanel === PanelView.Image ? (_jsx(ImagePanel, { object: object })) : currentPanel === PanelView.Video ? (_jsx(VideoPanel, { object: object })) : (isLoadingText ? (_jsx("div", { className: "flex justify-center items-center h-[calc(100vh-260px)]", children: _jsx(Spinner, { size: "lg" }) })) : (_jsx(TextPanel, { object: object, text: text, isTextCropped: isTextCropped })))] }));
}
function TextActions({ object, text, handleCopyContent }) {
    const { client } = useUserSession();
    const toast = useToast();
    const [loadingFormat, setLoadingFormat] = useState(null);
    const content = object.content;
    const isMarkdown = content &&
        content.type &&
        content.type === "text/markdown";
    const handleExportDocument = async (format) => {
        // Prevent multiple concurrent exports
        if (loadingFormat)
            return;
        setLoadingFormat(format);
        // Show immediate feedback
        toast({
            status: "info",
            title: `Preparing ${format.toUpperCase()}`,
            description: "Fetching your document...",
            duration: 2000,
        });
        try {
            // Request document rendition from the server
            const response = await client.objects.getRendition(object.id, {
                format: format, // We're extending the format type
                generate_if_missing: true,
                sign_url: true,
            });
            if (response.status === "generating") {
                toast({
                    status: "info",
                    title: "Generating document",
                    description: `Please wait while we prepare your ${format.toUpperCase()} file...`,
                    duration: 5000,
                });
                // Poll for completion
                setTimeout(() => handleExportDocument(format), 3000);
                return;
            }
            if (response.status === "failed") {
                throw new Error("Document generation failed");
            }
            // Download the generated file or open in new window
            if (response.renditions && response.renditions.length > 0) {
                const downloadUrl = response.renditions[0];
                if (format === 'pdf') {
                    // Open PDF in new window
                    window.open(downloadUrl, '_blank');
                    toast({
                        status: "success",
                        title: "PDF opened",
                        description: "PDF document opened in a new window",
                        duration: 2000,
                    });
                }
                else {
                    // Download DOCX file
                    const link = document.createElement("a");
                    link.href = downloadUrl;
                    link.download = `${object.name || "document"}.${format}`;
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                    toast({
                        status: "success",
                        title: "Document exported",
                        description: `Successfully exported to ${format.toUpperCase()} format`,
                        duration: 2000,
                    });
                }
            }
        }
        catch (err) {
            console.error(`Failed to export document as ${format}:`, err);
            toast({
                status: "error",
                title: "Export failed",
                description: `Failed to export document to ${format.toUpperCase()} format`,
                duration: 5000,
            });
        }
        finally {
            setLoadingFormat(null);
        }
    };
    const handleExportDocx = () => handleExportDocument("docx");
    const handleExportPdf = () => handleExportDocument("pdf");
    return (_jsx("div", { className: "h-[41px] text-lg font-semibold flex justify-between items-center px-2", children: _jsxs("div", { className: "flex items-center gap-2", children: [text && (_jsx(Button, { variant: "ghost", size: "sm", title: "Copy text", className: "flex items-center gap-2", onClick: () => handleCopyContent(text, "text"), children: _jsx(Copy, { className: "size-4" }) })), isMarkdown && text && (_jsxs(_Fragment, { children: [_jsxs(Button, { variant: "ghost", size: "sm", onClick: handleExportDocx, disabled: loadingFormat !== null, className: "flex items-center gap-2", children: [loadingFormat === "docx" ? (_jsx(Spinner, { size: "sm" })) : (_jsx(Download, { className: "size-4" })), "DOCX"] }), _jsxs(Button, { variant: "ghost", size: "sm", onClick: handleExportPdf, disabled: loadingFormat !== null, className: "flex items-center gap-2", children: [loadingFormat === "pdf" ? (_jsx(Spinner, { size: "sm" })) : (_jsx(Download, { className: "size-4" })), "PDF"] })] }))] }) }));
}
const TextPanel = memo(({ object, text, isTextCropped }) => {
    const content = object.content;
    // Check if content type is markdown or plain text
    const isMarkdownOrText = content &&
        content.type &&
        (content.type === "text/markdown" || content.type === "text/plain");
    // Check if text content looks like markdown
    const seemsMarkdown = text && (text.includes("\n# ") ||
        text.includes("\n## ") ||
        text.includes("\n### ") ||
        text.includes("\n* ") ||
        text.includes("\n- ") ||
        text.includes("\n+ ") ||
        text.includes("![") ||
        text.includes("]("));
    // Render as markdown if it's markdown/text type OR if text looks like markdown
    const shouldRenderAsMarkdown = isMarkdownOrText || seemsMarkdown;
    return (text ? (_jsxs(_Fragment, { children: [isTextCropped && (_jsx("div", { className: "px-2 py-2 bg-attention/10 border-l-4 border-attention mx-2 mb-2 rounded", children: _jsxs("div", { className: "flex items-center gap-2 text-attention", children: [_jsx(AlertTriangle, { className: "size-4" }), _jsx("span", { className: "text-sm font-semibold", children: "Showing first 128K characters only" })] }) })), _jsx("div", { className: "max-w-7xl px-2 h-[calc(100vh-210px)] overflow-auto", children: shouldRenderAsMarkdown ? (_jsx("div", { className: "vprose prose-sm p-1", children: _jsx(MarkdownRenderer, { components: {
                            a: ({ node, ...props }) => {
                                const href = props.href || "";
                                if (href.includes("/store/objects/")) {
                                    return (_jsx(NavLink, { topLevelNav: true, href: href, className: "text-info", children: props.children }));
                                }
                                return _jsx("a", { ...props, "data-debug": "test", target: "_blank", rel: "noopener noreferrer" });
                            },
                            p: ({ node, ...props }) => (_jsx("p", { ...props, className: `my-0` })),
                            pre: ({ node, ...props }) => (_jsx("pre", { ...props, className: `my-2 p-2 rounded` })),
                            code: ({ node, className, children, ...props }) => {
                                const match = /language-(\w+)/.exec(className || "");
                                const isInline = !match;
                                return (_jsx("code", { ...props, className: isInline
                                        ? `px-1.5 py-0.5 rounded`
                                        : "text-muted", children: children }));
                            },
                            h1: ({ node, ...props }) => (_jsx("h1", { ...props, className: `font-bold text-2xl my-2` })),
                            h2: ({ node, ...props }) => (_jsx("h2", { ...props, className: `font-bold text-xl my-2` })),
                            h3: ({ node, ...props }) => (_jsx("h3", { ...props, className: `font-bold text-lg my-2` })),
                            li: ({ node, ...props }) => (_jsx("li", { ...props })),
                        }, children: text }) })) : (_jsx("pre", { className: "text-wrap bg-muted text-muted p-2", children: text })) })] })) :
        _jsx("div", { className: "px-2", children: _jsx("div", { children: "No content" }) }));
});
function ImagePanel({ object }) {
    const { client } = useUserSession();
    const [imageUrl, setImageUrl] = useState();
    const content = object.content;
    const isImage = object.metadata && object.metadata.type === ContentNature.Image;
    useEffect(() => {
        if (isImage) {
            const loadImage = async () => {
                const webSupportedFormats = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml'];
                const isOriginalWebSupported = content?.type && webSupportedFormats.includes(content.type);
                try {
                    const rendition = await client.objects.getRendition(object.id, {
                        format: ImageRenditionFormat.jpeg,
                        generate_if_missing: false,
                        sign_url: true,
                    });
                    if (rendition.status === "found" && rendition.renditions?.length) {
                        // Use rendition URL directly
                        setImageUrl(rendition.renditions[0]);
                    }
                    else if (isOriginalWebSupported) {
                        // Fall back to original file only if web-supported
                        const downloadUrl = await client.files.getDownloadUrl(object.content.source);
                        setImageUrl(downloadUrl.url);
                    }
                }
                catch (error) {
                    // Fall back to original file only if web-supported
                    if (isOriginalWebSupported) {
                        const downloadUrl = await client.files.getDownloadUrl(object.content.source);
                        setImageUrl(downloadUrl.url);
                    }
                }
            };
            loadImage();
        }
    }, []);
    return (_jsx("div", { className: "mb-4 px-2", children: imageUrl ? (_jsx("img", { src: imageUrl, alt: object.name, className: "w-full object-contain" })) : (_jsx(Spinner, { size: "md" })) }));
}
function VideoPanel({ object }) {
    const { client } = useUserSession();
    const [videoUrl, setVideoUrl] = useState();
    const [posterUrl, setPosterUrl] = useState();
    const [isLoading, setIsLoading] = useState(true);
    const content = object.content;
    const isVideo = object.metadata?.type === ContentNature.Video;
    // Check if there are mp4 or webm renditions available in metadata
    const metadata = object.metadata;
    const renditions = metadata?.renditions || [];
    // Find mp4 or webm rendition by mime type, preferring mp4
    const webRendition = renditions.find(r => r.content.type === 'video/mp4') ||
        renditions.find(r => r.content.type === 'video/webm');
    // Check if original file is web-compatible
    const webSupportedFormats = ['video/mp4', 'video/webm'];
    const isOriginalWebSupported = content?.type && webSupportedFormats.includes(content.type);
    // Get poster
    const poster = renditions.find(r => r.name === POSTER_RENDITION_NAME);
    useEffect(() => {
        const loadPoster = async () => {
            if (poster?.content?.source) {
                try {
                    const response = await client.files.getDownloadUrl(poster.content.source);
                    setPosterUrl(response.url);
                }
                catch (error) {
                    console.error("Failed to load poster image", error);
                }
            }
        };
        loadPoster();
    }, [poster, client]);
    useEffect(() => {
        if (isVideo && (webRendition?.content?.source || isOriginalWebSupported)) {
            const loadVideoUrl = async () => {
                try {
                    let downloadUrl;
                    if (webRendition?.content?.source) {
                        // Use rendition if available
                        downloadUrl = await client.files.getDownloadUrl(webRendition.content.source);
                    }
                    else if (isOriginalWebSupported && content?.source) {
                        // Fall back to original file if web-supported
                        downloadUrl = await client.files.getDownloadUrl(content.source);
                    }
                    if (downloadUrl) {
                        setVideoUrl(downloadUrl.url);
                    }
                }
                catch (error) {
                    console.error("Failed to get video URL", error);
                }
                finally {
                    setIsLoading(false);
                }
            };
            loadVideoUrl();
        }
        else {
            setIsLoading(false);
        }
    }, [isVideo, webRendition, isOriginalWebSupported, content?.source, client]);
    return (_jsx("div", { className: "mb-4 px-2", children: !webRendition && !isOriginalWebSupported ? (_jsx("div", { className: "flex justify-center items-center h-[400px] text-muted", children: _jsxs("div", { className: "text-center", children: [_jsx("p", { children: "No web-compatible video rendition available" }), _jsx("p", { className: "text-sm mt-2", children: "MP4 or WebM format required" })] }) })) : isLoading ? (_jsx("div", { className: "flex justify-center items-center h-[400px]", children: _jsx(Spinner, { size: "md" }) })) : videoUrl ? (_jsx("video", { src: videoUrl, poster: posterUrl, controls: true, className: "w-full max-h-[calc(100vh-260px)] object-contain", children: "Your browser does not support the video tag." })) : (_jsx("div", { className: "flex justify-center items-center h-[400px] text-muted", children: "Failed to load video" })) }));
}
//# sourceMappingURL=ContentOverview.js.map