// Particle sphere — canvas-based, rotating "orb" of points + connecting lines + waveform halo
function ParticleOrb() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let dpr = Math.min(window.devicePixelRatio || 1, 2);
    let w = 0, h = 0;
    function resize() {
      const rect = canvas.getBoundingClientRect();
      w = rect.width; h = rect.height;
      canvas.width = w * dpr; canvas.height = h * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    }
    resize();
    const ro = new ResizeObserver(resize); ro.observe(canvas);

    // Generate fibonacci sphere points
    const N = 280;
    const points = [];
    const phi = Math.PI * (3 - Math.sqrt(5));
    for (let i = 0; i < N; i++) {
      const y = 1 - (i / (N - 1)) * 2;
      const r = Math.sqrt(1 - y * y);
      const t = phi * i;
      points.push({ x: Math.cos(t) * r, y, z: Math.sin(t) * r });
    }

    // Floating dust
    const dust = Array.from({ length: 60 }, () => ({
      x: (Math.random() - 0.5) * 2,
      y: (Math.random() - 0.5) * 2,
      z: (Math.random() - 0.5) * 2,
      s: Math.random() * 0.6 + 0.2,
      v: Math.random() * 0.4 + 0.1,
    }));

    let rx = 0.3, ry = 0;
    let raf;
    function frame(t) {
      ry += 0.0035;
      rx = 0.3 + Math.sin(t * 0.0004) * 0.15;
      ctx.clearRect(0, 0, w, h);

      const cx = w / 2, cy = h / 2;
      const radius = Math.min(w, h) * 0.32;

      const sinx = Math.sin(rx), cosx = Math.cos(rx);
      const siny = Math.sin(ry), cosy = Math.cos(ry);
      const proj = (p) => {
        let x = p.x, y = p.y, z = p.z;
        const x1 = x * cosy - z * siny;
        const z1 = x * siny + z * cosy;
        const y2 = y * cosx - z1 * sinx;
        const z2 = y * sinx + z1 * cosx;
        const persp = 1.4 / (1.6 - z2);
        return { sx: cx + x1 * radius * persp, sy: cy + y2 * radius * persp, depth: z2 };
      };

      const projected = points.map(proj);

      // Glow halo
      const grad = ctx.createRadialGradient(cx, cy, radius * 0.2, cx, cy, radius * 1.6);
      grad.addColorStop(0, 'rgba(16,185,129,0.20)');
      grad.addColorStop(0.5, 'rgba(6,182,212,0.10)');
      grad.addColorStop(1, 'rgba(0,0,0,0)');
      ctx.fillStyle = grad;
      ctx.fillRect(0, 0, w, h);

      // Connecting lines (only near-front points)
      ctx.lineWidth = 0.6;
      for (let i = 0; i < projected.length; i++) {
        const a = projected[i];
        if (a.depth < -0.2) continue;
        for (let j = i + 1; j < projected.length; j++) {
          const b = projected[j];
          if (b.depth < -0.2) continue;
          const dx = a.sx - b.sx, dy = a.sy - b.sy;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < radius * 0.28) {
            const alpha = (1 - d / (radius * 0.28)) * 0.12 * Math.max(0, (a.depth + b.depth) / 2 + 0.3);
            ctx.strokeStyle = `rgba(110,231,183,${alpha})`;
            ctx.beginPath();
            ctx.moveTo(a.sx, a.sy); ctx.lineTo(b.sx, b.sy);
            ctx.stroke();
          }
        }
      }

      // Points
      projected.forEach(p => {
        const depth01 = (p.depth + 1) / 2;
        const r = 0.6 + depth01 * 1.8;
        const c1 = `rgba(110, 231, 183, ${0.3 + depth01 * 0.6})`;
        const c2 = `rgba(34, 211, 238, ${0.2 + depth01 * 0.5})`;
        ctx.fillStyle = depth01 > 0.5 ? c1 : c2;
        ctx.beginPath();
        ctx.arc(p.sx, p.sy, r, 0, Math.PI * 2);
        ctx.fill();
      });

      // Dust
      dust.forEach(d => {
        d.y -= d.v * 0.002;
        if (d.y < -1.2) d.y = 1.2;
        const dp = proj(d);
        ctx.fillStyle = `rgba(163, 230, 53, ${0.3 * d.s})`;
        ctx.fillRect(dp.sx, dp.sy, d.s, d.s);
      });

      // Audio waveform circle (animated)
      const bars = 64;
      ctx.lineWidth = 1.2;
      for (let i = 0; i < bars; i++) {
        const ang = (i / bars) * Math.PI * 2;
        const amp = (Math.sin(t * 0.003 + i * 0.6) * 0.5 + Math.sin(t * 0.005 + i * 0.3) * 0.5) * 0.5 + 0.5;
        const r1 = radius * 1.18;
        const r2 = r1 + amp * 14 + 4;
        ctx.beginPath();
        ctx.moveTo(cx + Math.cos(ang) * r1, cy + Math.sin(ang) * r1);
        ctx.lineTo(cx + Math.cos(ang) * r2, cy + Math.sin(ang) * r2);
        const alpha = 0.15 + amp * 0.55;
        ctx.strokeStyle = `rgba(${i % 3 === 0 ? '163,230,53' : '34,211,238'}, ${alpha})`;
        ctx.stroke();
      }

      raf = requestAnimationFrame(frame);
    }
    raf = requestAnimationFrame(frame);
    return () => { cancelAnimationFrame(raf); ro.disconnect(); };
  }, []);
  return <canvas ref={ref} className="orb-canvas" />;
}

// Animated mini waveform bars (used in floating cards)
function WaveBars({ count = 14 }) {
  return (
    <div className="wave-mini">
      {Array.from({ length: count }).map((_, i) => (
        <div key={i} className="b" style={{
          height: `${20 + (i % 3) * 4}px`,
          animationDelay: `${i * 0.08}s`,
          animationDuration: `${1.1 + (i % 3) * 0.2}s`
        }}/>
      ))}
    </div>
  );
}

window.ParticleOrb = ParticleOrb;
window.WaveBars = WaveBars;
