// vita-waveform.jsx — animated voice visualizer (the "Vita orb")
// variants: 'barras' | 'espejo' | 'linea'
// states:   'idle' | 'listening' | 'thinking' | 'speaking'

function Waveform({ state = 'idle', accent = '#3DD9D6', accentDeep = '#16A8A5', variant = 'barras', size = 200, level = 0 }) {
  const canvasRef = React.useRef(null);
  const timerRef = React.useRef(0);
  const tRef = React.useRef(0);
  // smoothed target amplitude
  const ampRef = React.useRef(0.12);
  const stateRef = React.useRef(state);
  const levelRef = React.useRef(level);
  stateRef.current = state;
  levelRef.current = level;

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    canvas.width = size * dpr;
    canvas.height = size * dpr;
    ctx.scale(dpr, dpr);

    const targetFor = (s) => {
      if (s === 'speaking') return 0.92;
      if (s === 'listening') return 0.55;
      if (s === 'thinking') return 0.30;
      return 0.14; // idle
    };

    const hx = (hex, a) => {
      const h = hex.replace('#', '');
      return `rgba(${parseInt(h.slice(0,2),16)},${parseInt(h.slice(2,4),16)},${parseInt(h.slice(4,6),16)},${a})`;
    };

    const draw = () => {
      tRef.current += 0.045;
      const t = tRef.current;
      const s = stateRef.current;
      // approach target amplitude smoothly
      let target = targetFor(s);
      if (s === 'listening' || s === 'speaking') {
        target = Math.max(target * 0.5, Math.min(1, target + levelRef.current * 0.6));
      }
      ampRef.current += (target - ampRef.current) * 0.12;
      const amp = ampRef.current;
      const c = size / 2;

      ctx.clearRect(0, 0, size, size);

      // soft halo
      const halo = ctx.createRadialGradient(c, c, size * 0.15, c, c, size * 0.5);
      halo.addColorStop(0, hx(accent, 0.22 + amp * 0.22));
      halo.addColorStop(1, hx(accent, 0));
      ctx.fillStyle = halo;
      ctx.beginPath(); ctx.arc(c, c, size * 0.5, 0, Math.PI * 2); ctx.fill();

      const grad = ctx.createLinearGradient(0, c - size * 0.3, 0, c + size * 0.3);
      grad.addColorStop(0, accent);
      grad.addColorStop(1, accentDeep);

      if (variant === 'barras') {
        const N = 5;
        const barW = size * 0.052;
        const gap = size * 0.046;
        const totalW = N * barW + (N - 1) * gap;
        const startX = c - totalW / 2;
        ctx.fillStyle = grad;
        for (let i = 0; i < N; i++) {
          const phase = t * (s === 'thinking' ? 3 : 2.4) + i * 0.7;
          const mid = (N - 1) / 2;
          const weight = 1 - Math.abs(i - mid) / (mid + 1.2);
          const h = size * (0.10 + (0.5 * amp) * weight * (0.55 + 0.45 * Math.sin(phase)));
          const x = startX + i * (barW + gap);
          const y = c - h / 2;
          roundRect(ctx, x, y, barW, h, barW / 2);
          ctx.fill();
        }
      } else if (variant === 'espejo') {
        // centered mirrored line spectrum
        const N = 48;
        const spread = size * 0.74;
        const startX = c - spread / 2;
        ctx.lineWidth = size * 0.018;
        ctx.lineCap = 'round';
        ctx.strokeStyle = grad;
        for (let i = 0; i < N; i++) {
          const x = startX + (i / (N - 1)) * spread;
          const d = Math.abs(i - (N - 1) / 2) / ((N - 1) / 2); // 0 center → 1 edge
          const env = Math.cos(d * Math.PI / 2); // taper edges
          const wob = 0.5 + 0.5 * Math.sin(t * 2.2 + i * 0.55) * Math.sin(t * 1.3 + i * 0.2);
          const h = size * (0.012 + 0.42 * amp * env * wob);
          ctx.beginPath();
          ctx.moveTo(x, c - h);
          ctx.lineTo(x, c + h);
          ctx.stroke();
        }
      } else { // 'linea' — flowing dual sine
        const spread = size * 0.78;
        const startX = c - spread / 2;
        const drawWave = (alpha, phase, ampMul, lw) => {
          ctx.beginPath();
          for (let x = 0; x <= spread; x += 3) {
            const px = startX + x;
            const u = x / spread;
            const env = Math.sin(u * Math.PI); // 0 at ends
            const y = c + Math.sin(u * 9 + t * 3 + phase) * size * 0.30 * amp * env
                        + Math.sin(u * 4 - t * 1.7 + phase) * size * 0.12 * amp * env;
            if (x === 0) ctx.moveTo(px, y); else ctx.lineTo(px, y);
          }
          ctx.strokeStyle = hx(accent, alpha);
          ctx.lineWidth = lw; ctx.lineCap = 'round';
          ctx.stroke();
        };
        drawWave(0.35, 1.6, 0.7, size * 0.012);
        drawWave(0.6, 0.8, 0.85, size * 0.016);
        drawWave(1, 0, 1, size * 0.02);
      }

    };
    timerRef.current = setInterval(draw, 33);
    draw();
    return () => clearInterval(timerRef.current);
  }, [size, variant, accent, accentDeep]);

  return (
    <canvas
      ref={canvasRef}
      style={{ width: size, height: size, display: 'block' }}
    />
  );
}

function roundRect(ctx, x, y, w, h, r) {
  r = Math.min(r, w / 2, h / 2);
  ctx.beginPath();
  ctx.moveTo(x + r, y);
  ctx.arcTo(x + w, y, x + w, y + h, r);
  ctx.arcTo(x + w, y + h, x, y + h, r);
  ctx.arcTo(x, y + h, x, y, r);
  ctx.arcTo(x, y, x + w, y, r);
  ctx.closePath();
}

Object.assign(window, { Waveform });
