// hero-canvas.jsx — animated abstract background variants
// Provides <HeroCanvas variant accent /> with two modes: 'network' (particle web)
// and 'flow' (flowing curves) — plus a static 'off' fallback. Adapts to viewport,
// pauses on tab hidden, and reads CSS vars for current accent colors.

function HeroCanvas({ variant = "network", accent = "#00E6FF", accent2 = "#8B5CF6" }) {
  const ref = React.useRef(null);

  React.useEffect(() => {
    const canvas = ref.current;
    if (!canvas) return;
    if (variant === "off") return;

    const ctx = canvas.getContext("2d");
    let raf = 0;
    let running = true;

    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    let W = 0, H = 0;
    const resize = () => {
      const r = canvas.getBoundingClientRect();
      W = r.width; H = r.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);

    const onVis = () => { running = !document.hidden; if (running) loop(); };
    document.addEventListener("visibilitychange", onVis);

    // --- mouse interaction
    let mx = -9999, my = -9999;
    const onMove = (e) => {
      const r = canvas.getBoundingClientRect();
      mx = e.clientX - r.left;
      my = e.clientY - r.top;
    };
    const onLeave = () => { mx = -9999; my = -9999; };
    canvas.parentElement.addEventListener("mousemove", onMove);
    canvas.parentElement.addEventListener("mouseleave", onLeave);

    // ── NETWORK variant ───────────────────────────────────────
    const initNetwork = () => {
      const count = Math.min(90, Math.max(40, Math.round((W * H) / 22000)));
      const pts = [];
      for (let i = 0; i < count; i++) {
        pts.push({
          x: Math.random() * W,
          y: Math.random() * H,
          vx: (Math.random() - 0.5) * 0.25,
          vy: (Math.random() - 0.5) * 0.25,
          r: Math.random() * 1.2 + 0.4,
        });
      }
      return { pts };
    };

    const drawNetwork = (state, t) => {
      ctx.clearRect(0, 0, W, H);
      const { pts } = state;

      // update positions
      for (const p of pts) {
        p.x += p.vx;
        p.y += p.vy;
        if (p.x < 0 || p.x > W) p.vx *= -1;
        if (p.y < 0 || p.y > H) p.vy *= -1;

        // mouse repel
        const dx = p.x - mx, dy = p.y - my;
        const d2 = dx * dx + dy * dy;
        if (d2 < 18000) {
          const f = (1 - d2 / 18000) * 0.6;
          p.x += (dx / Math.sqrt(d2 + 1)) * f;
          p.y += (dy / Math.sqrt(d2 + 1)) * f;
        }
      }

      // edges
      const LINK = 140;
      for (let i = 0; i < pts.length; i++) {
        for (let j = i + 1; j < pts.length; j++) {
          const a = pts[i], b = pts[j];
          const dx = a.x - b.x, dy = a.y - b.y;
          const d = Math.sqrt(dx * dx + dy * dy);
          if (d < LINK) {
            const alpha = (1 - d / LINK) * 0.25;
            ctx.strokeStyle = hexA(accent, alpha);
            ctx.lineWidth = 0.5;
            ctx.beginPath();
            ctx.moveTo(a.x, a.y);
            ctx.lineTo(b.x, b.y);
            ctx.stroke();
          }
        }
      }

      // nodes
      for (const p of pts) {
        const dx = p.x - mx, dy = p.y - my;
        const near = Math.max(0, 1 - (dx * dx + dy * dy) / 28000);
        const r = p.r + near * 1.5;
        ctx.fillStyle = near > 0.1 ? accent : hexA(accent, 0.75);
        ctx.beginPath();
        ctx.arc(p.x, p.y, r, 0, Math.PI * 2);
        ctx.fill();
        if (near > 0.5) {
          ctx.fillStyle = hexA(accent, 0.2);
          ctx.beginPath();
          ctx.arc(p.x, p.y, r * 3.5, 0, Math.PI * 2);
          ctx.fill();
        }
      }
    };

    // ── FLOW variant — sine ribbons + drifting points ─────────
    const initFlow = () => {
      const dots = [];
      for (let i = 0; i < 80; i++) {
        dots.push({
          x: Math.random() * W,
          y: Math.random() * H,
          v: 0.2 + Math.random() * 0.5,
          r: Math.random() * 1.4 + 0.3,
          hue: Math.random(),
        });
      }
      return { dots };
    };

    const drawFlow = (state, t) => {
      ctx.clearRect(0, 0, W, H);
      const lines = 6;
      for (let l = 0; l < lines; l++) {
        const yBase = H * (0.2 + (0.6 * l) / (lines - 1));
        ctx.beginPath();
        ctx.strokeStyle = l % 2 === 0 ? hexA(accent, 0.18) : hexA(accent2, 0.18);
        ctx.lineWidth = 1;
        for (let x = 0; x <= W; x += 6) {
          const y =
            yBase +
            Math.sin((x * 0.006) + t * 0.0006 + l) * 22 +
            Math.sin((x * 0.013) + t * 0.0009 + l * 1.7) * 14;
          if (x === 0) ctx.moveTo(x, y);
          else ctx.lineTo(x, y);
        }
        ctx.stroke();
      }

      for (const d of state.dots) {
        d.x += d.v;
        if (d.x > W + 4) d.x = -4;
        ctx.fillStyle = d.hue > 0.5 ? hexA(accent, 0.8) : hexA(accent2, 0.7);
        ctx.beginPath();
        ctx.arc(d.x, d.y, d.r, 0, Math.PI * 2);
        ctx.fill();
      }
    };

    // ── main loop ──────────────────────────────────────────────
    let state = variant === "flow" ? initFlow() : initNetwork();
    const draw = variant === "flow" ? drawFlow : drawNetwork;

    const loop = (t = 0) => {
      if (!running) return;
      draw(state, t);
      raf = requestAnimationFrame(loop);
    };
    loop();

    return () => {
      cancelAnimationFrame(raf);
      ro.disconnect();
      document.removeEventListener("visibilitychange", onVis);
      canvas.parentElement?.removeEventListener("mousemove", onMove);
      canvas.parentElement?.removeEventListener("mouseleave", onLeave);
    };
  }, [variant, accent, accent2]);

  if (variant === "off") {
    return (
      <div className="hero-canvas" style={{
        background: `radial-gradient(ellipse at 70% 30%, ${hexA(accent, 0.08)} 0%, transparent 55%)`,
      }} />
    );
  }

  return <canvas ref={ref} className="hero-canvas" />;
}

// hexA — accept "#rgb" / "#rrggbb" and return rgba(...) with given alpha.
function hexA(hex, a) {
  const h = String(hex).replace("#", "");
  const x = h.length === 3 ? h.replace(/./g, (c) => c + c) : h.padEnd(6, "0");
  const n = parseInt(x.slice(0, 6), 16);
  const r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255;
  return `rgba(${r},${g},${b},${a})`;
}

window.HeroCanvas = HeroCanvas;
