/**
 * ImageViewer
 *
 * Full-featured image preview for the IDE tab. Built on
 * `react-zoom-pan-pinch` so it ships with:
 *
 *   - Wheel / pinch zoom
 *   - Click-and-drag pan
 *   - Zoom-to-cursor
 *
 * On top of that, this component layers a toolbar with:
 *
 *   - Zoom in / out buttons
 *   - Fit to screen, 1:1 actual size, reset
 *   - Rotate 90° CW / CCW
 *   - Horizontal / vertical flip
 *   - Background toggle (checkerboard → black → white → transparent)
 *   - Copy image URL + open in new tab + download
 *   - Live "Nx · 123 × 456 · 4.2 KB" info readout
 */
'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useMemo, useRef, useState } from 'react';
import { TransformWrapper, TransformComponent, } from 'react-zoom-pan-pinch';
import { Download, ExternalLink, FlipHorizontal2, FlipVertical2, Link as LinkIcon, Maximize2, Minus, Monitor, Plus, RotateCcw, RotateCw, Square, } from 'lucide-react';
import { toast } from 'sonner';
import { cn } from '../../../../lib/utils.js';
import { useResolvedTheme } from './use-resolved-theme.js';
/**
 * Build a theme-aware background-style map. In light mode the checkerboard
 * fades to soft grey on white; in dark mode it sits on the Monaco vs-dark
 * backdrop so images feel continuous with the editor.
 */
function makeBackgroundStyles(isDark) {
    const canvasBg = isDark ? '#1e1e1e' : '#ffffff';
    const checkerSquare = isDark ? '#2a2a2a' : '#e5e7eb';
    return {
        checkered: {
            backgroundImage: `linear-gradient(45deg, ${checkerSquare} 25%, transparent 25%), linear-gradient(-45deg, ${checkerSquare} 25%, transparent 25%), linear-gradient(45deg, transparent 75%, ${checkerSquare} 75%), linear-gradient(-45deg, transparent 75%, ${checkerSquare} 75%)`,
            backgroundSize: '16px 16px',
            backgroundPosition: '0 0, 0 8px, 8px -8px, -8px 0px',
            backgroundColor: canvasBg,
        },
        black: { backgroundColor: '#000000' },
        white: { backgroundColor: '#ffffff' },
        transparent: { backgroundColor: canvasBg },
    };
}
const BACKGROUND_CYCLE = ['checkered', 'black', 'white', 'transparent'];
function formatBytes(bytes) {
    if (bytes == null || Number.isNaN(bytes))
        return '—';
    if (bytes < 1024)
        return `${bytes} B`;
    if (bytes < 1024 * 1024)
        return `${(bytes / 1024).toFixed(1)} KB`;
    return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
}
function basename(p) {
    const i = p.lastIndexOf('/');
    return i === -1 ? p : p.slice(i + 1);
}
export function ImageViewer({ applicationId, path }) {
    const src = `/api/applications/${applicationId}/files/raw?path=${encodeURIComponent(path)}`;
    const resolvedTheme = useResolvedTheme();
    const isDark = resolvedTheme === 'dark';
    const backgroundStyles = useMemo(() => makeBackgroundStyles(isDark), [isDark]);
    const rootBgClass = isDark ? 'bg-[#1e1e1e]' : 'bg-[#ffffff]';
    const transformRef = useRef(null);
    const [bgMode, setBgMode] = useState('checkered');
    const [rotation, setRotation] = useState(0);
    const [flipH, setFlipH] = useState(false);
    const [flipV, setFlipV] = useState(false);
    const [scale, setScale] = useState(1);
    const [dimensions, setDimensions] = useState(null);
    const [bytes, setBytes] = useState(null);
    const [error, setError] = useState(null);
    // Reset all transforms whenever the path changes so switching images in
    // the same tab slot starts fresh instead of inheriting a prior zoom.
    useEffect(() => {
        setRotation(0);
        setFlipH(false);
        setFlipV(false);
        setScale(1);
        setDimensions(null);
        setBytes(null);
        setError(null);
        transformRef.current?.resetTransform?.();
    }, [path]);
    // Fetch the bytes once so we can display a size readout without
    // re-downloading (the browser also caches the <img> request).
    useEffect(() => {
        let cancelled = false;
        (async () => {
            try {
                const res = await fetch(src, { cache: 'no-store' });
                if (!res.ok) {
                    setError(`Failed to load image (${res.status})`);
                    return;
                }
                const buf = await res.arrayBuffer();
                if (!cancelled)
                    setBytes(buf.byteLength);
            }
            catch (err) {
                if (!cancelled)
                    setError(err instanceof Error ? err.message : String(err));
            }
        })();
        return () => {
            cancelled = true;
        };
    }, [src]);
    const cycleBackground = () => {
        setBgMode((prev) => {
            const idx = BACKGROUND_CYCLE.indexOf(prev);
            return BACKGROUND_CYCLE[(idx + 1) % BACKGROUND_CYCLE.length];
        });
    };
    const rotateCw = () => setRotation((r) => (r + 90) % 360);
    const rotateCcw = () => setRotation((r) => (r + 270) % 360);
    const copyUrl = async () => {
        try {
            const absolute = new URL(src, window.location.origin).toString();
            await navigator.clipboard.writeText(absolute);
            toast.success('Image URL copied');
        }
        catch {
            toast.error('Failed to copy URL');
        }
    };
    if (error) {
        return (_jsx("div", { className: cn('flex h-full items-center justify-center text-xs text-red-500 dark:text-red-400', rootBgClass), children: error }));
    }
    return (_jsxs("div", { className: cn('flex h-full min-h-0 flex-col', rootBgClass), children: [_jsx(Toolbar, { scale: scale, dimensions: dimensions, bytes: bytes, bgMode: bgMode, flipH: flipH, flipV: flipV, onZoomIn: () => transformRef.current?.zoomIn?.(0.25), onZoomOut: () => transformRef.current?.zoomOut?.(0.25), onReset: () => transformRef.current?.resetTransform?.(), onFit: () => transformRef.current?.centerView?.(1), onActualSize: () => transformRef.current?.setTransform?.(0, 0, 1), onRotateCcw: rotateCcw, onRotateCw: rotateCw, onFlipH: () => setFlipH((v) => !v), onFlipV: () => setFlipV((v) => !v), onCycleBackground: cycleBackground, onCopyUrl: copyUrl, onOpenInNewTab: () => window.open(src, '_blank', 'noopener,noreferrer'), downloadHref: src, downloadName: basename(path) }), _jsx("div", { className: "relative min-h-0 flex-1 overflow-hidden", style: backgroundStyles[bgMode], children: _jsx(TransformWrapper, { ref: transformRef, initialScale: 1, minScale: 0.1, maxScale: 40, centerOnInit: true, 
                    // Wheel zoom: tiny per-tick delta so trackpads don't launch into orbit.
                    // `step` is fraction-of-current-scale per wheel event; 0.05 ≈ 5%.
                    wheel: { step: 0.05 }, doubleClick: { mode: 'reset' }, pinch: { step: 2 }, onTransform: (_ref, state) => setScale(state.scale), children: _jsx(TransformComponent, { wrapperStyle: { width: '100%', height: '100%' }, contentStyle: { width: '100%', height: '100%' }, children: _jsx("div", { className: "flex h-full w-full items-center justify-center", children: _jsx("img", { src: src, alt: path, draggable: false, onLoad: (e) => {
                                    const img = e.currentTarget;
                                    setDimensions({ w: img.naturalWidth, h: img.naturalHeight });
                                }, style: {
                                    transform: `rotate(${rotation}deg) scaleX(${flipH ? -1 : 1}) scaleY(${flipV ? -1 : 1})`,
                                    transformOrigin: 'center',
                                    maxWidth: '90%',
                                    maxHeight: '90%',
                                    objectFit: 'contain',
                                    imageRendering: scale >= 4 ? 'pixelated' : 'auto',
                                    transition: 'transform 120ms ease',
                                } }) }) }) }) })] }));
}
function Toolbar({ scale, dimensions, bytes, bgMode, flipH, flipV, onZoomIn, onZoomOut, onReset, onFit, onActualSize, onRotateCcw, onRotateCw, onFlipH, onFlipV, onCycleBackground, onCopyUrl, onOpenInNewTab, downloadHref, downloadName, }) {
    return (_jsxs("div", { className: "border-border bg-background/95 text-muted-foreground flex h-9 shrink-0 items-center gap-0.5 border-b px-2 text-[11px]", children: [_jsx(ToolButton, { label: "Zoom out", onClick: onZoomOut, icon: _jsx(Minus, { className: "h-3.5 w-3.5" }) }), _jsx(ToolButton, { label: "Zoom in", onClick: onZoomIn, icon: _jsx(Plus, { className: "h-3.5 w-3.5" }) }), _jsxs("button", { type: "button", onClick: onReset, className: "text-foreground hover:bg-muted/60 h-6 min-w-[3.25rem] rounded-sm px-1.5 text-center font-mono tabular-nums", title: "Reset zoom", children: [Math.round(scale * 100), "%"] }), _jsx(Separator, {}), _jsx(ToolButton, { label: "Fit to screen", onClick: onFit, icon: _jsx(Maximize2, { className: "h-3.5 w-3.5" }) }), _jsx(ToolButton, { label: "Actual size (1:1)", onClick: onActualSize, icon: _jsx(Square, { className: "h-3.5 w-3.5" }) }), _jsx(Separator, {}), _jsx(ToolButton, { label: "Rotate 90\u00B0 counter-clockwise", onClick: onRotateCcw, icon: _jsx(RotateCcw, { className: "h-3.5 w-3.5" }) }), _jsx(ToolButton, { label: "Rotate 90\u00B0 clockwise", onClick: onRotateCw, icon: _jsx(RotateCw, { className: "h-3.5 w-3.5" }) }), _jsx(ToolButton, { label: "Flip horizontal", onClick: onFlipH, icon: _jsx(FlipHorizontal2, { className: "h-3.5 w-3.5" }), active: flipH }), _jsx(ToolButton, { label: "Flip vertical", onClick: onFlipV, icon: _jsx(FlipVertical2, { className: "h-3.5 w-3.5" }), active: flipV }), _jsx(Separator, {}), _jsx(ToolButton, { label: `Background: ${bgMode}`, onClick: onCycleBackground, icon: _jsx(Monitor, { className: "h-3.5 w-3.5" }) }), _jsx(ToolButton, { label: "Copy URL", onClick: onCopyUrl, icon: _jsx(LinkIcon, { className: "h-3.5 w-3.5" }) }), _jsx(ToolButton, { label: "Open in new tab", onClick: onOpenInNewTab, icon: _jsx(ExternalLink, { className: "h-3.5 w-3.5" }) }), _jsx("a", { href: downloadHref, download: downloadName, className: "text-muted-foreground hover:text-foreground hover:bg-muted/60 flex h-6 w-6 items-center justify-center rounded-sm", title: "Download", children: _jsx(Download, { className: "h-3.5 w-3.5" }) }), _jsx("div", { className: "flex-1" }), _jsxs("div", { className: "flex items-center gap-2 font-mono text-[10px]", children: [dimensions ? (_jsxs("span", { children: [dimensions.w, " \u00D7 ", dimensions.h] })) : null, _jsx("span", { children: formatBytes(bytes) })] })] }));
}
/* ------------------------------------------------------------------ */
/*  Toolbar building blocks                                            */
/* ------------------------------------------------------------------ */
function Separator() {
    return _jsx("span", { className: "bg-border/60 mx-1 h-4 w-px shrink-0" });
}
function ToolButton({ label, onClick, icon, active, }) {
    return (_jsx("button", { type: "button", onClick: onClick, "aria-label": label, title: label, className: cn('hover:bg-muted/60 flex h-6 w-6 items-center justify-center rounded-sm transition-colors', active ? 'text-foreground bg-muted/60' : 'text-muted-foreground hover:text-foreground'), children: icon }));
}
