// 3×3 graphical pattern input. Dots indexed 0..8 (row-major).
// Props:
//   onComplete(pattern: string) — called when pointer up with ≥ minDots
//   onChange?(pattern: string)
//   minDots = 4
//   disabled = false
//   resetKey — changing this resets state (e.g. after save)

const PATTERN_SIZE = 300;
const PATTERN_RADIUS = 40; // hit-test radius
const DOTS = (() => {
  const out = [];
  for (let y = 0; y < 3; y++) {
    for (let x = 0; x < 3; x++) {
      out.push({ id: y * 3 + x, cx: 50 + x * 100, cy: 50 + y * 100 });
    }
  }
  return out;
})();

const PatternInput = ({ onComplete, onChange, minDots = 4, disabled = false, resetKey = 0 }) => {
  const [points, setPoints] = React.useState([]);
  const [cursor, setCursor] = React.useState(null);
  const drawingRef = React.useRef(false);
  const svgRef = React.useRef(null);

  React.useEffect(() => {
    setPoints([]);
    setCursor(null);
    drawingRef.current = false;
  }, [resetKey]);

  const svgCoords = (e) => {
    const svg = svgRef.current;
    if (!svg) return { x: 0, y: 0 };
    const pt = svg.createSVGPoint();
    pt.x = e.clientX;
    pt.y = e.clientY;
    const ctm = svg.getScreenCTM();
    if (!ctm) return { x: 0, y: 0 };
    const t = pt.matrixTransform(ctm.inverse());
    return { x: t.x, y: t.y };
  };

  const dotAt = (x, y) => {
    for (const d of DOTS) {
      if (Math.hypot(x - d.cx, y - d.cy) < PATTERN_RADIUS) return d.id;
    }
    return null;
  };

  const start = (e) => {
    if (disabled) return;
    e.preventDefault();
    const p = svgCoords(e);
    const id = dotAt(p.x, p.y);
    if (id == null) return;
    drawingRef.current = true;
    setPoints([id]);
    setCursor(p);
    if (svgRef.current?.setPointerCapture) {
      try { svgRef.current.setPointerCapture(e.pointerId); } catch {}
    }
  };

  const move = (e) => {
    if (!drawingRef.current) return;
    const p = svgCoords(e);
    setCursor(p);
    const id = dotAt(p.x, p.y);
    if (id != null) {
      setPoints((prev) => (prev.includes(id) ? prev : [...prev, id]));
    }
  };

  const end = (e) => {
    if (!drawingRef.current) return;
    drawingRef.current = false;
    setCursor(null);
    const current = points;
    if (current.length >= minDots) {
      const str = current.join(',');
      onChange?.(str);
      onComplete?.(str);
    } else {
      setPoints([]);
    }
  };

  let path = '';
  points.forEach((id, i) => {
    const d = DOTS[id];
    path += (i === 0 ? 'M' : ' L') + ' ' + d.cx + ' ' + d.cy;
  });
  if (cursor && drawingRef.current && points.length) {
    path += ' L ' + cursor.x.toFixed(1) + ' ' + cursor.y.toFixed(1);
  }

  return (
    <svg
      ref={svgRef}
      viewBox={`0 0 ${PATTERN_SIZE} ${PATTERN_SIZE}`}
      style={{
        width: '100%', maxWidth: 280, aspectRatio: '1',
        touchAction: 'none', userSelect: 'none',
        margin: '0 auto', display: 'block',
        background: 'var(--surface-2)', borderRadius: 16,
        border: '1px solid var(--border)',
        opacity: disabled ? 0.5 : 1,
      }}
      onPointerDown={start}
      onPointerMove={move}
      onPointerUp={end}
      onPointerCancel={end}
      onPointerLeave={(e) => { if (drawingRef.current) end(e); }}
    >
      <path d={path} stroke="var(--accent)" strokeWidth="6" fill="none"
            strokeLinejoin="round" strokeLinecap="round" opacity="0.9"/>
      {DOTS.map((d) => {
        const active = points.includes(d.id);
        return (
          <g key={d.id}>
            <circle cx={d.cx} cy={d.cy} r={PATTERN_RADIUS} fill="transparent"/>
            <circle cx={d.cx} cy={d.cy} r={active ? 18 : 10}
                    fill={active ? 'var(--accent)' : 'var(--border-strong)'}
                    style={{ transition: 'r .12s ease, fill .12s ease' }}/>
            {active && (
              <circle cx={d.cx} cy={d.cy} r={28} fill="var(--accent)" opacity="0.18"/>
            )}
          </g>
        );
      })}
    </svg>
  );
};

Object.assign(window, { PatternInput });
