// CSS Cubic Bezier Editor — interactive curve editor with draggable control points,
// presets, animation preview, and CSS output.

window.TOOL_HANDLERS['css-cubic-bezier'] = function CssCubicBezierTool() {
  const PRESETS = [
    { name: 'ease',         v: [0.25, 0.1, 0.25, 1.0] },
    { name: 'ease-in',      v: [0.42, 0, 1, 1] },
    { name: 'ease-out',     v: [0, 0, 0.58, 1] },
    { name: 'ease-in-out',  v: [0.42, 0, 0.58, 1] },
    { name: 'linear',       v: [0, 0, 1, 1] },
    { name: 'snap',         v: [0, 1, 0.5, 1] },
    { name: 'bounce-start', v: [0.6, -0.28, 0.74, 0.05] },
    { name: 'swift',        v: [0.55, 0, 0.1, 1] },
  ];

  const [p1, setP1] = React.useState({ x: 0.25, y: 0.1 });
  const [p2, setP2] = React.useState({ x: 0.25, y: 1.0 });
  const [duration, setDuration] = React.useState(0.5);
  const [playing, setPlaying] = React.useState(false);
  const [copied, setCopied] = React.useState(false);
  const dragging = React.useRef(null);
  const svgRef = React.useRef(null);
  const animKey = React.useRef(0);

  const SIZE = 200;
  const PAD = 16;
  const FULL = SIZE + PAD * 2;

  // Convert curve coords (0-1, with Y going up) to SVG pixel coords
  const toSvg = (cx, cy) => ({
    sx: PAD + cx * SIZE,
    sy: PAD + (1 - cy) * SIZE,
  });

  // Convert SVG pixel coords to curve coords
  const fromSvg = (sx, sy) => ({
    cx: Math.max(0, Math.min(1, (sx - PAD) / SIZE)),
    cy: Math.max(-0.5, Math.min(1.5, 1 - (sy - PAD) / SIZE)),
  });

  const startP0 = toSvg(0, 0);
  const endP1 = toSvg(1, 1);
  const cp1 = toSvg(p1.x, p1.y);
  const cp2 = toSvg(p2.x, p2.y);

  const curvePath = `M ${startP0.sx} ${startP0.sy} C ${cp1.sx} ${cp1.sy}, ${cp2.sx} ${cp2.sy}, ${endP1.sx} ${endP1.sy}`;

  const handleMouseDown = (which) => (e) => {
    e.preventDefault();
    dragging.current = which;
  };

  React.useEffect(() => {
    const handleMouseMove = (e) => {
      if (!dragging.current || !svgRef.current) return;
      const rect = svgRef.current.getBoundingClientRect();
      const sx = ((e.clientX - rect.left) / rect.width) * FULL;
      const sy = ((e.clientY - rect.top) / rect.height) * FULL;
      const { cx, cy } = fromSvg(sx, sy);
      if (dragging.current === 'p1') setP1({ x: cx, y: cy });
      else setP2({ x: cx, y: cy });
    };
    const handleMouseUp = () => { dragging.current = null; };
    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp);
    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('mouseup', handleMouseUp);
    };
  }, []);

  const applyPreset = (v) => {
    setP1({ x: v[0], y: v[1] });
    setP2({ x: v[2], y: v[3] });
  };

  const fmt = (n) => parseFloat(n.toFixed(2));
  const cssValue = `cubic-bezier(${fmt(p1.x)}, ${fmt(p1.y)}, ${fmt(p2.x)}, ${fmt(p2.y)})`;
  const cssLine = `transition-timing-function: ${cssValue};`;

  const copyCSS = () => {
    navigator.clipboard.writeText(cssLine);
    setCopied(true);
    setTimeout(() => setCopied(false), 1500);
  };

  const playAnimation = () => {
    animKey.current++;
    setPlaying(false);
    requestAnimationFrame(() => setPlaying(true));
  };

  // Grid lines for the SVG
  const gridLines = [];
  for (let i = 0; i <= 4; i++) {
    const pos = PAD + (i / 4) * SIZE;
    gridLines.push(
      <line key={`gv${i}`} x1={pos} y1={PAD} x2={pos} y2={PAD + SIZE}
            stroke="var(--id-border)" strokeWidth="0.5" />,
      <line key={`gh${i}`} x1={PAD} y1={pos} x2={PAD + SIZE} y2={pos}
            stroke="var(--id-border)" strokeWidth="0.5" />
    );
  }

  return (
    <div className="mini-tool">
      <style>{`
        .cbz-wrap { display: grid; grid-template-columns: auto 1fr; gap: 24px; align-items: start; }
        .cbz-svg-box {
          background: var(--id-surface-alt);
          border: 1px solid var(--id-border);
          border-radius: 12px; padding: 8px; display: inline-block;
          user-select: none; touch-action: none;
        }
        .cbz-cp { cursor: grab; transition: r 120ms ease; }
        .cbz-cp:hover { r: 8; }
        .cbz-controls { display: flex; flex-direction: column; gap: 16px; }
        .cbz-presets { display: flex; flex-wrap: wrap; gap: 6px; }
        .cbz-output {
          font-family: 'JetBrains Mono', monospace; font-size: 13px;
          background: var(--id-surface-alt); border: 1px solid var(--id-border);
          border-radius: 8px; padding: 12px 14px; color: var(--id-text);
          word-break: break-all; line-height: 1.5;
        }
        .cbz-anim-track {
          background: var(--id-surface-alt); border: 1px solid var(--id-border);
          border-radius: 8px; padding: 12px; position: relative;
          height: 48px; overflow: hidden;
        }
        .cbz-anim-ball {
          width: 32px; height: 32px; border-radius: 8px;
          background: var(--id-brand-blue); position: absolute;
          top: 50%; transform: translateY(-50%); left: 8px;
        }
        .cbz-anim-ball.running {
          animation-name: cbz-slide;
          animation-fill-mode: forwards;
        }
        @keyframes cbz-slide {
          from { left: 8px; }
          to { left: calc(100% - 40px); }
        }
        .cbz-dur-row { display: flex; align-items: center; gap: 10px; }
        .cbz-dur-row input[type=range] { flex: 1; }
        .cbz-dur-row .cbz-dur-val {
          font-size: 13px; font-weight: 600; min-width: 36px;
          text-align: right; color: var(--id-text);
        }
        .cbz-axis-label {
          font-size: 9px; fill: var(--id-text-muted);
          font-family: 'JetBrains Mono', monospace;
        }
        @media (max-width: 600px) {
          .cbz-wrap { grid-template-columns: 1fr; }
          .cbz-svg-box { justify-self: center; }
        }
      `}</style>

      <div className="cbz-wrap">
        {/* SVG curve editor */}
        <div className="cbz-svg-box">
          <svg ref={svgRef} width={FULL} height={FULL} viewBox={`0 0 ${FULL} ${FULL}`}
               style={{ display: 'block', maxWidth: '100%', height: 'auto' }}>
            {/* Grid */}
            {gridLines}
            {/* Bounding box */}
            <rect x={PAD} y={PAD} width={SIZE} height={SIZE}
                  fill="none" stroke="var(--id-border-strong)" strokeWidth="1" rx="2" />
            {/* Handle lines */}
            <line x1={startP0.sx} y1={startP0.sy} x2={cp1.sx} y2={cp1.sy}
                  stroke="var(--id-text-muted)" strokeWidth="1" strokeDasharray="4 3" />
            <line x1={endP1.sx} y1={endP1.sy} x2={cp2.sx} y2={cp2.sy}
                  stroke="var(--id-text-muted)" strokeWidth="1" strokeDasharray="4 3" />
            {/* Curve */}
            <path d={curvePath} fill="none" stroke="var(--id-brand-blue)" strokeWidth="2.5" />
            {/* Endpoints */}
            <circle cx={startP0.sx} cy={startP0.sy} r="4" fill="var(--id-text-muted)" />
            <circle cx={endP1.sx} cy={endP1.sy} r="4" fill="var(--id-text-muted)" />
            {/* Control points */}
            <circle cx={cp1.sx} cy={cp1.sy} r="6" fill="#ea580c" className="cbz-cp"
                    onMouseDown={handleMouseDown('p1')} />
            <circle cx={cp2.sx} cy={cp2.sy} r="6" fill="#7c3aed" className="cbz-cp"
                    onMouseDown={handleMouseDown('p2')} />
            {/* Axis labels */}
            <text x={PAD + SIZE / 2} y={FULL - 2} textAnchor="middle" className="cbz-axis-label">time</text>
            <text x={4} y={PAD + SIZE / 2} textAnchor="middle" className="cbz-axis-label"
                  transform={`rotate(-90, 6, ${PAD + SIZE / 2})`}>progress</text>
          </svg>
        </div>

        {/* Right-side controls */}
        <div className="cbz-controls">
          {/* Presets */}
          <div>
            <label className="mini-label">Presets</label>
            <div className="cbz-presets">
              {PRESETS.map((pr) => (
                <button key={pr.name} className="filter-pill" onClick={() => applyPreset(pr.v)}>
                  {pr.name}
                </button>
              ))}
            </div>
          </div>

          {/* Control point values */}
          <div className="mini-row">
            <div className="mini-field">
              <label className="mini-label" style={{ color: '#ea580c' }}>P1 ({fmt(p1.x)}, {fmt(p1.y)})</label>
            </div>
            <div className="mini-field">
              <label className="mini-label" style={{ color: '#7c3aed' }}>P2 ({fmt(p2.x)}, {fmt(p2.y)})</label>
            </div>
          </div>

          {/* CSS output */}
          <div>
            <label className="mini-label">CSS Output</label>
            <div className="cbz-output">{cssLine}</div>
          </div>

          {/* Duration */}
          <div>
            <label className="mini-label">Duration</label>
            <div className="cbz-dur-row">
              <input type="range" min="0.1" max="3" step="0.1" value={duration}
                     onChange={(e) => setDuration(parseFloat(e.target.value))}
                     className="cmp-slider" />
              <span className="cbz-dur-val">{duration.toFixed(1)}s</span>
            </div>
          </div>

          {/* Animation preview */}
          <div>
            <label className="mini-label">Preview</label>
            <div className="cbz-anim-track">
              <div key={animKey.current}
                   className={`cbz-anim-ball ${playing ? 'running' : ''}`}
                   style={playing ? {
                     animationDuration: duration + 's',
                     animationTimingFunction: cssValue,
                   } : {}} />
            </div>
          </div>

          <div className="cmp-actions" style={{ marginTop: 0 }}>
            <button className="btn btn-secondary" onClick={playAnimation}>
              <window.Icon name="zap" size={16} /> Play
            </button>
            <button className="btn btn-primary" onClick={copyCSS}>
              <window.Icon name={copied ? 'check' : 'doc'} size={16} /> {copied ? 'Copied!' : 'Copy CSS'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};
