// ImageEditor.jsx — drag-to-reposition + pinch/scroll zoom for circular timer image

const { useState, useRef, useEffect, useCallback } = React;

function ImageEditor({ imageData, initialTransform, onSave, onCancel }) {
  const stageRef = useRef(null);
  const imgRef = useRef(null);
  const [imgSize, setImgSize] = useState({ w: 0, h: 0 });
  const [stageSize, setStageSize] = useState({ w: 360, h: 360 });

  // Transform state — px coords (centered)
  const [tx, setTx] = useState(initialTransform?.tx || 0);
  const [ty, setTy] = useState(initialTransform?.ty || 0);
  const [scale, setScale] = useState(initialTransform?.scale || 1);
  const [rotate, setRotate] = useState(initialTransform?.rotate || 0);

  // Drag tracking
  const dragRef = useRef(null);
  // Pinch tracking
  const pinchRef = useRef(null);

  // Load image dimensions
  useEffect(() => {
    if (!imageData) return;
    const i = new Image();
    i.onload = () => setImgSize({ w: i.naturalWidth, h: i.naturalHeight });
    i.src = imageData;
  }, [imageData]);

  // Measure stage size
  useEffect(() => {
    if (!stageRef.current) return;
    const r = stageRef.current.getBoundingClientRect();
    setStageSize({ w: r.width, h: r.height });
    const ro = new ResizeObserver(() => {
      const rr = stageRef.current.getBoundingClientRect();
      setStageSize({ w: rr.width, h: rr.height });
    });
    ro.observe(stageRef.current);
    return () => ro.disconnect();
  }, []);

  // Compute base size — fit image so it covers the circle initially
  const baseSize = (() => {
    if (!imgSize.w || !stageSize.w) return { w: 0, h: 0 };
    const stageDim = Math.min(stageSize.w, stageSize.h);
    const r = imgSize.w / imgSize.h;
    // Cover: take max
    if (r >= 1) {
      return { w: stageDim * r, h: stageDim };
    } else {
      return { w: stageDim, h: stageDim / r };
    }
  })();

  const onPointerDown = (e) => {
    if (e.pointerType === "touch") return; // handled by touch
    e.currentTarget.setPointerCapture(e.pointerId);
    dragRef.current = { x: e.clientX, y: e.clientY, tx, ty };
  };
  const onPointerMove = (e) => {
    if (!dragRef.current) return;
    const dx = e.clientX - dragRef.current.x;
    const dy = e.clientY - dragRef.current.y;
    setTx(dragRef.current.tx + dx);
    setTy(dragRef.current.ty + dy);
  };
  const onPointerUp = (e) => {
    dragRef.current = null;
  };

  const onWheel = (e) => {
    e.preventDefault();
    const delta = -e.deltaY * 0.0015;
    setScale((s) => clamp(s * (1 + delta), 0.5, 4));
  };

  // Touch handlers (pinch + pan)
  const touchesRef = useRef(new Map());
  const onTouchStart = (e) => {
    for (const t of e.touches) {
      touchesRef.current.set(t.identifier, { x: t.clientX, y: t.clientY });
    }
    if (e.touches.length === 1) {
      dragRef.current = { x: e.touches[0].clientX, y: e.touches[0].clientY, tx, ty };
      pinchRef.current = null;
    } else if (e.touches.length === 2) {
      const [a, b] = [e.touches[0], e.touches[1]];
      const dist = Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY);
      pinchRef.current = { startDist: dist, startScale: scale };
      dragRef.current = null;
    }
  };
  const onTouchMove = (e) => {
    e.preventDefault();
    if (e.touches.length === 1 && dragRef.current) {
      const dx = e.touches[0].clientX - dragRef.current.x;
      const dy = e.touches[0].clientY - dragRef.current.y;
      setTx(dragRef.current.tx + dx);
      setTy(dragRef.current.ty + dy);
    } else if (e.touches.length === 2 && pinchRef.current) {
      const [a, b] = [e.touches[0], e.touches[1]];
      const dist = Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY);
      const ratio = dist / pinchRef.current.startDist;
      setScale(clamp(pinchRef.current.startScale * ratio, 0.5, 4));
    }
  };
  const onTouchEnd = (e) => {
    touchesRef.current.clear();
    dragRef.current = null;
    pinchRef.current = null;
  };

  const handleSave = () => {
    // Convert to relative offsets so it works regardless of disk size.
    // We store as % offsets relative to stage size, plus scale.
    const xPct = (tx / stageSize.w) * 100;
    const yPct = (ty / stageSize.h) * 100;
    // Scale we store is the multiplier on the "cover-fit" base.
    onSave({
      tx, ty, scale, rotate,
      xPct, yPct,
      // For background-image rendering on the disk later:
      bgScale: scale,
      bgXPct: -xPct, // we move image right → bg position moves "left" % in CSS
      bgYPct: -yPct,
    });
  };

  return (
    <div className="modal-backdrop" onClick={onCancel}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3 className="modal-title">Position your image</h3>
        <p className="modal-sub">Drag to move. Pinch or scroll to zoom.</p>

        <div
          ref={stageRef}
          className="editor-stage"
          onPointerDown={onPointerDown}
          onPointerMove={onPointerMove}
          onPointerUp={onPointerUp}
          onPointerCancel={onPointerUp}
          onWheel={onWheel}
          onTouchStart={onTouchStart}
          onTouchMove={onTouchMove}
          onTouchEnd={onTouchEnd}
        >
          {imageData && baseSize.w > 0 && (
            <img
              ref={imgRef}
              src={imageData}
              alt=""
              className="editor-img"
              style={{
                width: baseSize.w,
                height: baseSize.h,
                transform: `translate(-50%, -50%) translate(${tx}px, ${ty}px) scale(${scale}) rotate(${rotate}deg)`,
              }}
            />
          )}
        </div>

        <div className="editor-zoom">
          <span className="label">Zoom</span>
          <input
            type="range"
            min="0.5" max="4" step="0.01"
            value={scale}
            onChange={(e) => setScale(parseFloat(e.target.value))}
          />
          <button
            className="btn btn-small"
            onClick={() => setRotate((r) => (r + 90) % 360)}
            title="Rotate"
          >↻ 90°</button>
        </div>

        <div className="modal-actions">
          <button className="btn btn-ghost" onClick={onCancel}>Cancel</button>
          <button className="btn btn-primary" onClick={handleSave}>Done</button>
        </div>
      </div>
    </div>
  );
}

function clamp(v, lo, hi) { return Math.min(hi, Math.max(lo, v)); }

Object.assign(window, { ImageEditor });
