// ==========================================
// snippet.js: THE CUT & PASTE ENGINE
// ==========================================

window.extractCanvasSnippet = function(container, rectX, rectY, rectW, rectH, bgColor = "#ffffff", isCopyMode = false) {
    const pageCanvas = container.querySelector('.pageCanvas');
    if (!pageCanvas) return;

    const wrapper = container.closest('.pageWrapper');
    const displayW = parseFloat(wrapper.dataset.baseWidth) || parseFloat(container.style.width);
    const displayH = parseFloat(wrapper.dataset.baseHeight) || parseFloat(container.style.height);
    
    const scaleX = pageCanvas.width / displayW;
    const scaleY = pageCanvas.height / displayH;

    // Whole CSS pixels for placement + integer canvas samples (avoids half-pixel seams)
    let cssX = Math.round(rectX);
    let cssY = Math.round(rectY);
    let cssW = Math.max(1, Math.round(rectW));
    let cssH = Math.max(1, Math.round(rectH));
    // Clamp into page
    cssX = Math.max(0, Math.min(cssX, Math.max(0, Math.round(displayW) - 1)));
    cssY = Math.max(0, Math.min(cssY, Math.max(0, Math.round(displayH) - 1)));
    cssW = Math.min(cssW, Math.max(1, Math.round(displayW) - cssX));
    cssH = Math.min(cssH, Math.max(1, Math.round(displayH) - cssY));

    // Map CSS → canvas with integer source rect (round after scale so lines stay sharp)
    let sx = Math.round(cssX * scaleX);
    let sy = Math.round(cssY * scaleY);
    let sw = Math.max(1, Math.round(cssW * scaleX));
    let sh = Math.max(1, Math.round(cssH * scaleY));
    // Keep source inside canvas
    if (sx + sw > pageCanvas.width) sw = Math.max(1, pageCanvas.width - sx);
    if (sy + sh > pageCanvas.height) sh = Math.max(1, pageCanvas.height - sy);

    // Re-derive CSS size from the actual canvas sample so display box matches pixels 1:1
    cssW = Math.max(1, Math.round(sw / scaleX));
    cssH = Math.max(1, Math.round(sh / scaleY));

    const tempCanvas = document.createElement("canvas");
    tempCanvas.width = sw;
    tempCanvas.height = sh;
    const ctx = tempCanvas.getContext("2d", { alpha: false });
    // Nearest-neighbor sample into temp — avoids blurry edge lines when re-placed
    ctx.imageSmoothingEnabled = false;
    ctx.drawImage(
        pageCanvas,
        sx, sy, sw, sh,
        0, 0, sw, sh
    );
    
    const base64Data = tempCanvas.toDataURL("image/png");

    // --- 1. THE WHITEOUT PATCH (Only if NOT copying) ---
    let whiteout = null;
    if (!isCopyMode) {
        whiteout = document.createElement("div");
        whiteout.className = "shapeOverlay shape-rect"; 
        whiteout.style.left = cssX + "px";
        whiteout.style.top = cssY + "px";
        whiteout.style.width = cssW + "px";
        whiteout.style.height = cssH + "px";
        whiteout.style.backgroundColor = bgColor;
        whiteout.style.position = "absolute";
        whiteout.style.boxSizing = "border-box";
        // Same layer as other decorative overlays (CSS .shapeOverlay z-index: 10).
        // Do NOT force a high inline z-index — that buried text/toolbars under the snip.
        whiteout.style.border = "none";
        whiteout.style.margin = "0px";
        whiteout.style.padding = "0px";

        const woDrag = document.createElement("div"); woDrag.className = "textDragHandle"; woDrag.innerHTML = "⠿";
        const woResize = document.createElement("div"); woResize.className = "resizeHandle";
        const woDel = window.createDeleteHandle ? window.createDeleteHandle(whiteout) : document.createElement("div"); 
        
        whiteout.append(woDrag, woDel, woResize);
        container.appendChild(whiteout);
        if (window.makeDraggable) window.makeDraggable(whiteout, woResize, woDrag);
    }

    // --- 2. THE DRAGGABLE SNIPPET ---
    const snippet = document.createElement("div");
    snippet.className = "overlayImg"; 
    snippet.style.left = cssX + "px"; 
    snippet.style.top = cssY + "px";
    snippet.style.width = cssW + "px";
    snippet.style.height = cssH + "px";
    snippet.style.position = "absolute";
    snippet.style.boxSizing = "border-box";
    snippet.style.border = "none";
    snippet.style.margin = "0px";
    snippet.style.padding = "0px";
    snippet.dataset.snippet = "1";

    const img = document.createElement("img");
    img.src = base64Data;
    img.style.width = "100%";
    img.style.height = "100%";
    img.style.pointerEvents = "none";
    img.style.display = "block";
    img.style.imageRendering = "pixelated"; // keep hard table lines when zoomed 

    const snipDrag = document.createElement("div"); snipDrag.className = "textDragHandle"; snipDrag.innerHTML = "⠿";
    const snipRotate = document.createElement("div"); snipRotate.className = "rotateHandle"; snipRotate.innerHTML = "&#8635;";
    const snipResize = document.createElement("div"); snipResize.className = "resizeHandle";
    const snipDel = window.createDeleteHandle ? window.createDeleteHandle(snippet) : document.createElement("div");

    snippet.append(img, snipDrag, snipRotate, snipDel, snipResize);
    container.appendChild(snippet);
    
    if (window.makeDraggable) window.makeDraggable(snippet, snipResize, snipDrag);
    
    if (window.setActiveOverlay) {
        setTimeout(() => window.setActiveOverlay(snippet), 10);
    }

    // --- 3. Instruction tape (macro commit) ---
    // createNode assigns stack z (max+1) in call order: whiteout first, then snip on top.
    if (window.CcsProcessor) {
        const steps = [];
        if (whiteout) {
            steps.push(window.CcsProcessor.build.createNode(whiteout, "Whiteout"));
        }
        steps.push(window.CcsProcessor.build.createNode(snippet, "Snippet"));
        window.CcsProcessor.commit(
            window.CcsProcessor.build.compound(
                steps,
                isCopyMode ? "Copy Snippet" : "Cut & Paste Snippet"
            )
        );
    }
};
