// ==========================================
// SpritePreview Component
// ==========================================

const SpritePreview = ({ imageUrl, settings, removeBg, bgColorHex, tolerance, pixelated }) => {
    const canvasRef = React.useRef(null);
    const [isPlaying, setIsPlaying] = React.useState(true);
    const [currentFrame, setCurrentFrame] = React.useState(0);

    const requestRef = React.useRef();
    const previousTimeRef = React.useRef();
    const imageObjRef = React.useRef(null);

    const totalFrames = (Number(settings.rows) || 1) * (Number(settings.columns) || 1);

    const animate = React.useCallback((time) => {
        if (!isPlaying) return;

        if (previousTimeRef.current !== undefined) {
            const deltaTime = time - previousTimeRef.current;
            const interval = 1000 / (settings.fps || 1);

            if (deltaTime > interval) {
                setCurrentFrame((prev) => (prev + 1) % (totalFrames || 1));
                previousTimeRef.current = time - (deltaTime % interval);
            }
        } else {
            previousTimeRef.current = time;
        }
        requestRef.current = requestAnimationFrame(animate);
    }, [settings.fps, isPlaying, totalFrames]);

    React.useEffect(() => {
        if (isPlaying) {
            requestRef.current = requestAnimationFrame(animate);
        } else {
            if (requestRef.current) cancelAnimationFrame(requestRef.current);
        }
        return () => {
            if (requestRef.current) cancelAnimationFrame(requestRef.current);
        };
    }, [isPlaying, animate]);

    React.useEffect(() => {
        setCurrentFrame(0);
    }, [imageUrl, settings.columns, settings.rows]);

    React.useEffect(() => {
        const canvas = canvasRef.current;
        const image = imageObjRef.current;
        if (!canvas || !image) return;

        const ctx = canvas.getContext('2d', { willReadFrequently: true });
        if (!ctx) return;

        const cols = Math.max(1, Number(settings.columns) || 1);
        const rows = Math.max(1, Number(settings.rows) || 1);

        const frameWidth = Math.floor(image.naturalWidth / cols);
        const frameHeight = Math.floor(image.naturalHeight / rows);

        const safeWidth = Math.max(1, frameWidth);
        const safeHeight = Math.max(1, frameHeight);

        if (canvas.width !== safeWidth) canvas.width = safeWidth;
        if (canvas.height !== safeHeight) canvas.height = safeHeight;

        const col = currentFrame % cols;
        const row = Math.floor(currentFrame / cols);

        const srcX = col * frameWidth;
        const srcY = row * frameHeight;

        ctx.imageSmoothingEnabled = !pixelated;
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        ctx.drawImage(
            image,
            srcX, srcY, frameWidth, frameHeight,
            0, 0, safeWidth, safeHeight
        );

        if (removeBg) {
            const imageData = ctx.getImageData(0, 0, safeWidth, safeHeight);
            const data = imageData.data;
            const targetRgb = window.ColorUtils.hexToRgb(bgColorHex);

            for (let i = 0; i < data.length; i += 4) {
                if (window.ColorUtils.isColorMatch(data[i], data[i + 1], data[i + 2], targetRgb, tolerance)) {
                    data[i + 3] = 0;
                }
            }
            ctx.putImageData(imageData, 0, 0);
        }
    }, [currentFrame, imageUrl, settings, removeBg, bgColorHex, tolerance, pixelated]);

    React.useEffect(() => {
        const img = new Image();
        img.crossOrigin = "anonymous";
        img.src = imageUrl;
        img.onload = () => {
            imageObjRef.current = img;
            setCurrentFrame(0);
        };
    }, [imageUrl]);

    return (
        <div className="relative w-full h-full flex items-center justify-center bg-[#0f172a] rounded-xl overflow-hidden shadow-inner border border-slate-800 p-4">
            {/* Background checkerboard layer */}
            <div className="absolute inset-0 opacity-10 bg-[url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ib3BhY2l0eSI+PHJlY3Qgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiBmaWxsPSIjMWUyOTNiIiAvPjxyZWN0IHg9IjEwIiB5PSIxMCIgd2lkdGg9IjEwIiBoZWlnaHQ9IjEwIiBmaWxsPSIjMWUyOTNiIiAvPjwvc3ZnPg==')]" />

            <canvas
                ref={canvasRef}
                className="relative z-10 object-contain"
                style={{
                    imageRendering: pixelated ? 'pixelated' : 'auto',
                    maxWidth: '100%',
                    maxHeight: '100%'
                }}
            />

            <div className="absolute top-2 left-2 z-20 flex gap-1">
                <div className="bg-black/40 backdrop-blur-md px-2 py-1 rounded text-[9px] font-black text-slate-400 uppercase tracking-tighter border border-white/5">
                    {settings.cellWidth}×{settings.cellHeight}
                </div>
            </div>

            <button
                onClick={() => setIsPlaying(!isPlaying)}
                className="absolute top-2 right-2 bg-black/60 hover:bg-black/80 text-white p-2 rounded-lg backdrop-blur-sm transition-all z-20 border border-white/10 group"
            >
                {isPlaying ? (
                    <div className="flex gap-1">
                        <div className="w-1 h-3 bg-white rounded-full group-hover:scale-y-110 transition-transform"></div>
                        <div className="w-1 h-3 bg-white rounded-full group-hover:scale-y-110 transition-transform"></div>
                    </div>
                ) : (
                    <div className="w-0 h-0 border-t-[6px] border-t-transparent border-l-[10px] border-l-white border-b-[6px] border-b-transparent ml-0.5"></div>
                )}
            </button>

            <div className="absolute bottom-2 left-2 bg-black/60 text-[10px] font-black text-white px-3 py-1.5 rounded-lg backdrop-blur-sm font-mono tracking-wider border border-white/5 z-20">
                FRM {currentFrame + 1} / {totalFrames}
            </div>
        </div>
    );
};

window.SpritePreview = SpritePreview;
