// InkCanvas.jsx — iPad Sidecar ink surface, ported from the legacy SPA.
// Strokes buffer + pointer events + DPR-correct redraw all live in refs so
// React re-renders never blow away the imperative state.

function InkCanvas({ onFirstStroke, canvasRef, penColor = "#222", penWidth = 2, eraserMode = false }) {
  const wrapRef = React.useRef(null);
  const localCanvasRef = React.useRef(null);
  const strokesRef = React.useRef([]);
  const currentStrokeRef = React.useRef([]);
  const drawingRef = React.useRef(false);
  const hasDrawnRef = React.useRef(false);

  // Expose canvas + imperative handles to the parent via canvasRef.
  React.useImperativeHandle(canvasRef, () => ({
    getCanvas: () => localCanvasRef.current,
    toDataURL: (...a) => localCanvasRef.current.toDataURL(...a),
    clear: () => { strokesRef.current = []; redraw(); },
    undo: () => { strokesRef.current.pop(); redraw(); },
    hasDrawn: () => hasDrawnRef.current,
  }), []);

  const redraw = React.useCallback(() => {
    const canvas = localCanvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    const dpr = window.devicePixelRatio || 1;
    const w = canvas.width / dpr, h = canvas.height / dpr;
    ctx.clearRect(0, 0, w, h);

    ctx.strokeStyle = "rgba(173,89,5,0.08)";
    ctx.lineWidth = 0.5;
    for (let x = 0; x < w; x += 24) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, h); ctx.stroke(); }
    for (let y = 0; y < h; y += 24) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(w, y); ctx.stroke(); }

    for (const stroke of strokesRef.current) {
      if (stroke.length < 2) continue;
      ctx.strokeStyle = stroke[0].eraser ? "#fff" : stroke[0].color;
      ctx.lineWidth = stroke[0].eraser ? stroke[0].width * 4 : stroke[0].width;
      ctx.lineCap = "round"; ctx.lineJoin = "round";
      ctx.globalCompositeOperation = stroke[0].eraser ? "destination-out" : "source-over";
      ctx.beginPath();
      ctx.moveTo(stroke[0].x, stroke[0].y);
      for (let i = 1; i < stroke.length; i++) ctx.lineTo(stroke[i].x, stroke[i].y);
      ctx.stroke();
    }
    ctx.globalCompositeOperation = "source-over";
  }, []);

  const resize = React.useCallback(() => {
    const canvas = localCanvasRef.current;
    const wrap = wrapRef.current;
    if (!canvas || !wrap) return;
    const dpr = window.devicePixelRatio || 1;
    canvas.width = wrap.clientWidth * dpr;
    canvas.height = wrap.clientHeight * dpr;
    canvas.style.width = wrap.clientWidth + "px";
    canvas.style.height = wrap.clientHeight + "px";
    canvas.getContext("2d").scale(dpr, dpr);
    redraw();
  }, [redraw]);

  React.useEffect(() => {
    resize();
    window.addEventListener("resize", resize);
    return () => window.removeEventListener("resize", resize);
  }, [resize]);

  const getPos = (e) => {
    const rect = localCanvasRef.current.getBoundingClientRect();
    return { x: e.clientX - rect.left, y: e.clientY - rect.top };
  };

  const onPointerDown = (e) => {
    if (e.pointerType === "touch") return;
    e.preventDefault();
    drawingRef.current = true;
    const pos = getPos(e);
    currentStrokeRef.current = [{ ...pos, color: penColor, width: penWidth, eraser: eraserMode }];
  };

  const onPointerMove = (e) => {
    if (!drawingRef.current || e.pointerType === "touch") return;
    e.preventDefault();
    const pos = getPos(e);
    const stroke = currentStrokeRef.current;
    stroke.push({ ...pos, color: penColor, width: penWidth, eraser: eraserMode });
    if (stroke.length >= 2) {
      const ctx = localCanvasRef.current.getContext("2d");
      const prev = stroke[stroke.length - 2];
      const curr = stroke[stroke.length - 1];
      ctx.strokeStyle = eraserMode ? "#fff" : penColor;
      ctx.lineWidth = eraserMode ? penWidth * 4 : penWidth;
      ctx.lineCap = "round"; ctx.lineJoin = "round";
      ctx.globalCompositeOperation = eraserMode ? "destination-out" : "source-over";
      ctx.beginPath(); ctx.moveTo(prev.x, prev.y); ctx.lineTo(curr.x, curr.y); ctx.stroke();
      ctx.globalCompositeOperation = "source-over";
    }
  };

  const onPointerUp = (e) => {
    if (!drawingRef.current || (e && e.pointerType === "touch")) return;
    drawingRef.current = false;
    const stroke = currentStrokeRef.current;
    if (stroke.length > 1) {
      strokesRef.current.push(stroke);
      if (!hasDrawnRef.current) {
        hasDrawnRef.current = true;
        onFirstStroke && onFirstStroke();
      }
    }
    currentStrokeRef.current = [];
  };

  return (
    <div ref={wrapRef} className="ink-wrap">
      <canvas
        ref={localCanvasRef}
        className="ink-canvas"
        onPointerDown={onPointerDown}
        onPointerMove={onPointerMove}
        onPointerUp={onPointerUp}
        onPointerLeave={onPointerUp}
        onPointerCancel={onPointerUp}
      />
    </div>
  );
}

Object.assign(window, { InkCanvas });
