// SignaturePad — draw-to-sign, on a canvas.
//
// The typed name is the operative electronic signature (intent + attribution).
// This is the audit artifact that sits beside it, and it captures two things,
// because they answer different questions:
//
//   image  a PNG of the mark — what a human looks at in an audit pack
//   meta   how it was drawn: point count, elapsed time, pointer type, canvas
//          size. A pasted or scripted signature arrives in ~0ms with a handful
//          of points; a drawn one takes a second or two and produces hundreds.
//          That distinction is the difference between a picture of a signature
//          and evidence that a person signed.
//
// Pointer Events rather than separate mouse and touch handlers, so a stylus, a
// finger and a trackpad take one code path and `pointerType` is recorded rather
// than inferred. Drawing happens in CSS pixels while the backing store is
// scaled by devicePixelRatio, so the exported PNG is sharp on retina.

function SignaturePad({ onChange }) {
  const { React } = window;
  const { useRef, useEffect, useState, useCallback } = React;

  const canvasRef = useRef(null);
  const drawing = useRef(false);
  const strokes = useRef([]);       // [[{x,y}, …], …] — kept to replay on resize
  const current = useRef(null);
  const startedAt = useRef(null);
  const pointerType = useRef(null);
  const [hasInk, setHasInk] = useState(false);

  const fit = useCallback(() => {
    const c = canvasRef.current;
    if (!c) return;
    const r = c.getBoundingClientRect();
    const dpr = window.devicePixelRatio || 1;
    c.width = Math.round(r.width * dpr);
    c.height = Math.round(r.height * dpr);
    const ctx = c.getContext('2d');
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    ctx.lineWidth = 2;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.strokeStyle = getComputedStyle(c).color || '#1d1d1f';
    // Replay, so resizing the window doesn't wipe a signature in progress.
    strokes.current.forEach((s) => {
      ctx.beginPath();
      s.forEach((p, i) => (i ? ctx.lineTo(p.x, p.y) : ctx.moveTo(p.x, p.y)));
      ctx.stroke();
    });
  }, []);

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

  const emit = useCallback(() => {
    const c = canvasRef.current;
    if (!c) return;
    const points = strokes.current.reduce((n, s) => n + s.length, 0);
    if (!points) { onChange(null); return; }
    const r = c.getBoundingClientRect();
    onChange({
      image: c.toDataURL('image/png'),
      meta: {
        points,
        strokes: strokes.current.length,
        durationMs: startedAt.current ? Date.now() - startedAt.current : 0,
        pointerType: pointerType.current || 'unknown',
        width: Math.round(r.width),
        height: Math.round(r.height),
      },
    });
  }, [onChange]);

  const at = (e) => {
    const r = canvasRef.current.getBoundingClientRect();
    return { x: e.clientX - r.left, y: e.clientY - r.top };
  };

  const down = (e) => {
    e.preventDefault();
    canvasRef.current.setPointerCapture(e.pointerId);
    pointerType.current = e.pointerType || 'unknown';
    if (!startedAt.current) startedAt.current = Date.now();
    drawing.current = true;
    current.current = [at(e)];
    strokes.current.push(current.current);
    setHasInk(true);
  };

  const move = (e) => {
    if (!drawing.current) return;
    e.preventDefault();
    const p = at(e);
    const s = current.current;
    const prev = s[s.length - 1];
    s.push(p);
    const ctx = canvasRef.current.getContext('2d');
    ctx.beginPath();
    ctx.moveTo(prev.x, prev.y);
    ctx.lineTo(p.x, p.y);
    ctx.stroke();
  };

  const up = (e) => {
    if (!drawing.current) return;
    drawing.current = false;
    current.current = null;
    try { canvasRef.current.releasePointerCapture(e.pointerId); } catch { /* already released */ }
    emit();
  };

  const clear = () => {
    const c = canvasRef.current;
    c.getContext('2d').clearRect(0, 0, c.width, c.height);
    strokes.current = [];
    startedAt.current = null;
    setHasInk(false);
    onChange(null);
  };

  return (
    <div className="ah-sig">
      <div className="ah-sig-frame">
        <canvas
          ref={canvasRef}
          className="ah-sig-canvas"
          onPointerDown={down}
          onPointerMove={move}
          onPointerUp={up}
          onPointerLeave={up}
          onPointerCancel={up}
          role="img"
          aria-label="Signature area — draw your signature here"
        />
        {!hasInk && <span className="ah-sig-placeholder" aria-hidden="true">Sign here</span>}
        <span className="ah-sig-rule" aria-hidden="true" />
      </div>
      <div className="ah-sig-actions">
        <button type="button" className="ah-sig-clear" onClick={clear} disabled={!hasInk}>Clear</button>
        <span className="ah-caption">Draw with a mouse, finger, or stylus.</span>
      </div>
    </div>
  );
}

window.SignaturePad = SignaturePad;
