// brain-canvas.jsx — living AI neural brain (interactive) + ambient neural backdrop
// mode="hero": brain-shaped, idea particles, follows pointer, click = idea burst
// mode="backdrop": wide low-density neural field behind page headers

function BrainCanvas({ h = 440, mode = 'hero' }) {
  const wrapRef = React.useRef(null);
  const canvasRef = React.useRef(null);
  const isBackdrop = mode === 'backdrop';

  React.useEffect(() => {
    const canvas = canvasRef.current;
    const wrap = wrapRef.current;
    if (!canvas || !wrap) return;
    const ctx = canvas.getContext('2d');
    let raf, W = 0, H = 0, dpr = Math.min(2, window.devicePixelRatio || 1), roRaf = 0;
    let nodes = [], edges = [], pulses = [], ideas = [];
    let t0 = performance.now(), running = true;
    const mouse = { x: -1e9, y: -1e9, active: false };

    const C = { mint: [31, 209, 163], purple: [138, 109, 255], gold: [231, 179, 74] };
    const rgba = (c, a) => `rgba(${c[0]},${c[1]},${c[2]},${a})`;
    const A = isBackdrop ? 0.5 : 1;       // global alpha scale for backdrop

    function inBrain(x, y) {
      const e = (x * x) / (0.95 * 0.95) + (y * y) / (0.78 * 0.78);
      if (e > 1) return false;
      if (y > 0.55 && Math.abs(x) > 0.5) return false;
      return true;
    }

    function build() {
      const r = wrap.getBoundingClientRect();
      W = Math.round(r.width); H = Math.round(r.height);
      if (W === 0 || H === 0) return;
      canvas.width = W * dpr; canvas.height = H * dpr;
      canvas.style.width = W + 'px'; canvas.style.height = H + 'px';
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);

      const bx = W * (isBackdrop ? 0.5 : 0.46), by = H * 0.5;
      const br = isBackdrop ? Math.max(W, H) * 0.6 : Math.min(W, H) * 0.42;

      nodes = [];
      const density = isBackdrop ? 9000 : 5200;
      const N = Math.round(Math.min(isBackdrop ? 46 : 64, Math.max(isBackdrop ? 18 : 34, (W * H) / density)));
      let guard = 0;
      while (nodes.length < N && guard < N * 60) {
        guard++;
        let px, py, nx, ny;
        if (isBackdrop) {
          nx = Math.random() * 2 - 1; ny = Math.random() * 2 - 1;
          px = Math.random() * W; py = Math.random() * H;
        } else {
          nx = Math.random() * 2 - 1; ny = Math.random() * 2 - 1;
          if (!inBrain(nx, ny)) continue;
          if (Math.abs(nx) < 0.06 && Math.random() < 0.6) continue;
          px = bx + nx * br; py = by + ny * br;
        }
        nodes.push({ x: px, y: py, bx: px, by: py, nx, ny,
          r: (isBackdrop ? 1.0 : 1.4) + Math.random() * (isBackdrop ? 1.6 : 2.2),
          ph: Math.random() * Math.PI * 2,
          hue: Math.random() < 0.5 ? C.mint : (Math.random() < 0.6 ? C.purple : C.gold) });
      }

      edges = [];
      const linkR = isBackdrop ? br * 0.32 : br * 0.62;
      for (let i = 0; i < nodes.length; i++) {
        const order = [];
        for (let j = 0; j < nodes.length; j++) {
          if (i === j) continue;
          order.push([Math.hypot(nodes[i].x - nodes[j].x, nodes[i].y - nodes[j].y), j]);
        }
        order.sort((a, b) => a[0] - b[0]);
        for (let k = 0; k < Math.min(3, order.length); k++) {
          if (order[k][0] < linkR) edges.push([i, order[k][1]]);
        }
      }
      pulses = [];
      for (let i = 0; i < (isBackdrop ? 4 : 14); i++) spawnPulse();
      if (!isBackdrop && ideas.length === 0) for (let i = 0; i < 16; i++) { spawnIdea(); ideas[ideas.length - 1].life = Math.random(); }
    }

    function spawnPulse() {
      if (!edges.length) return;
      const e = edges[(Math.random() * edges.length) | 0];
      pulses.push({ e, p: 0, sp: 0.010 + Math.random() * 0.016 });
    }
    function spawnIdea(fromX, fromY) {
      let sx, sy;
      if (fromX != null) { sx = fromX; sy = fromY; }
      else {
        const cand = nodes.filter(n => n.ny < 0.25);
        const n = (cand.length ? cand : nodes)[(Math.random() * (cand.length ? cand.length : nodes.length)) | 0];
        if (!n) return; sx = n.x; sy = n.y;
      }
      const ang = -Math.PI / 2 + (Math.random() - 0.5) * 1.6;
      const sp = 0.7 + Math.random() * 1.4;
      const hue = Math.random() < 0.45 ? C.gold : (Math.random() < 0.6 ? C.mint : C.purple);
      ideas.push({ x: sx, y: sy, vx: Math.cos(ang) * sp, vy: Math.sin(ang) * sp,
        life: 0, sz: 2 + Math.random() * 2.8, hue, spark: Math.random() < 0.45 });
    }

    let ideaTimer = 0, pulseTimer = 0, emitTimer = 0;
    function frame(now) {
      if (!running) return;
      const dt = Math.min(40, now - t0) / 16.67; t0 = now;
      ctx.clearRect(0, 0, W, H);
      const ti = now / 1000;

      if (!isBackdrop) {
        const bx = W * 0.46, by = H * 0.5;
        const g = ctx.createRadialGradient(bx, by, 0, bx, by, Math.min(W, H) * 0.6);
        g.addColorStop(0, 'rgba(31,209,163,0.10)');
        g.addColorStop(0.5, 'rgba(138,109,255,0.07)');
        g.addColorStop(1, 'rgba(0,0,0,0)');
        ctx.fillStyle = g; ctx.fillRect(0, 0, W, H);
      }

      // node motion + pointer parallax/attraction
      for (const n of nodes) {
        n.x = n.bx + Math.sin(ti * 0.6 + n.ph) * (isBackdrop ? 2.4 : 1.6);
        n.y = n.by + Math.cos(ti * 0.5 + n.ph) * (isBackdrop ? 2.4 : 1.6);
        n._g = 0;
        if (mouse.active) {
          const dx = mouse.x - n.x, dy = mouse.y - n.y;
          const d2 = dx * dx + dy * dy;
          const R = 130;
          if (d2 < R * R) {
            const d = Math.sqrt(d2) || 1;
            const f = (1 - d / R);
            // gentle attraction toward pointer
            n.x += (dx / d) * f * 8;
            n.y += (dy / d) * f * 8;
            n._g = f;            // glow boost
          }
        }
        const pulse = Math.sin(ti * 1.9 + n.ph) * 3.2;
        n._r = n.r + (pulse > 0 ? pulse * 0.55 : 0) + n._g * 1.6;
      }

      // edges (brighten near pointer)
      ctx.lineWidth = 1;
      for (const [a, b] of edges) {
        const na = nodes[a], nb = nodes[b];
        const boost = Math.max(na._g, nb._g);
        const grd = ctx.createLinearGradient(na.x, na.y, nb.x, nb.y);
        grd.addColorStop(0, rgba(na.hue, (0.16 + boost * 0.5) * A));
        grd.addColorStop(1, rgba(nb.hue, (0.16 + boost * 0.5) * A));
        ctx.strokeStyle = grd;
        ctx.beginPath(); ctx.moveTo(na.x, na.y); ctx.lineTo(nb.x, nb.y); ctx.stroke();
      }

      // pulses
      pulseTimer += dt;
      if (pulseTimer > 3) { pulseTimer = 0; if (pulses.length < (isBackdrop ? 8 : 26)) spawnPulse(); }
      for (let i = pulses.length - 1; i >= 0; i--) {
        const pu = pulses[i]; pu.p += pu.sp * dt;
        if (pu.p >= 1) { pulses.splice(i, 1); continue; }
        const na = nodes[pu.e[0]], nb = nodes[pu.e[1]];
        if (!na || !nb) { pulses.splice(i, 1); continue; }
        const x = na.x + (nb.x - na.x) * pu.p, y = na.y + (nb.y - na.y) * pu.p;
        ctx.fillStyle = rgba(C.mint, 0.9 * A);
        ctx.shadowColor = rgba(C.mint, 0.9); ctx.shadowBlur = 8;
        ctx.beginPath(); ctx.arc(x, y, 1.8, 0, 7); ctx.fill();
        ctx.shadowBlur = 0;
      }

      // nodes
      for (const n of nodes) {
        ctx.fillStyle = rgba(n.hue, (0.95) * A + n._g * 0.05);
        ctx.shadowColor = rgba(n.hue, 0.8); ctx.shadowBlur = 7 + n._g * 8;
        ctx.beginPath(); ctx.arc(n.x, n.y, n._r, 0, 7); ctx.fill();
      }
      ctx.shadowBlur = 0;

      // ideas (hero only)
      if (!isBackdrop) {
        ideaTimer += dt;
        if (ideaTimer > 4) { ideaTimer = 0; if (ideas.length < 46) spawnIdea(); }
        // emit ideas near pointer when hovering the brain
        if (mouse.active) {
          emitTimer += dt;
          if (emitTimer > 6 && ideas.length < 40) { emitTimer = 0; spawnIdea(mouse.x + (Math.random() - 0.5) * 20, mouse.y); }
        }
        for (let i = ideas.length - 1; i >= 0; i--) {
          const p = ideas[i];
          p.life += 0.011 * dt;
          if (p.life >= 1) { ideas.splice(i, 1); continue; }
          p.vy -= 0.004 * dt; p.vx *= 0.995;
          p.x += p.vx * dt; p.y += p.vy * dt;
          const a = Math.sin(p.life * Math.PI);
          const sz = p.sz * (0.6 + p.life * 0.9);
          ctx.shadowColor = rgba(p.hue, a); ctx.shadowBlur = 12;
          if (p.spark) {
            ctx.strokeStyle = rgba(p.hue, a); ctx.lineWidth = 1.4; ctx.lineCap = 'round';
            ctx.beginPath();
            ctx.moveTo(p.x - sz, p.y); ctx.lineTo(p.x + sz, p.y);
            ctx.moveTo(p.x, p.y - sz); ctx.lineTo(p.x, p.y + sz);
            ctx.stroke();
          } else {
            ctx.fillStyle = rgba(p.hue, a);
            ctx.beginPath(); ctx.arc(p.x, p.y, sz, 0, 7); ctx.fill();
          }
        }
        ctx.shadowBlur = 0;
      }

      raf = requestAnimationFrame(frame);
    }

    build();
    frame(performance.now());

    // pointer interaction
    const toLocal = (e) => {
      const r = canvas.getBoundingClientRect();
      const cx = (e.touches ? e.touches[0].clientX : e.clientX);
      const cy = (e.touches ? e.touches[0].clientY : e.clientY);
      mouse.x = cx - r.left; mouse.y = cy - r.top;
      // for backdrop, only activate when pointer is actually over the header band
      if (isBackdrop) mouse.active = (cy >= r.top && cy <= r.bottom && cx >= r.left && cx <= r.right);
      else mouse.active = true;
    };
    const onLeave = () => { mouse.active = false; mouse.x = -1e9; mouse.y = -1e9; };
    const onClick = (e) => {
      if (isBackdrop) return;
      toLocal(e);
      for (let i = 0; i < 14; i++) spawnIdea(mouse.x + (Math.random() - 0.5) * 30, mouse.y + (Math.random() - 0.5) * 16);
    };
    if (isBackdrop) {
      // listen on window so the backdrop reacts without blocking clicks on header content
      window.addEventListener('pointermove', toLocal, { passive: true });
    } else {
      wrap.addEventListener('pointermove', toLocal);
      wrap.addEventListener('pointerleave', onLeave);
      wrap.addEventListener('pointerdown', onClick);
    }

    const ro = new ResizeObserver(() => {
      const r = wrap.getBoundingClientRect();
      const nw = Math.round(r.width), nh = Math.round(r.height);
      // only rebuild on a real size change — prevents ResizeObserver feedback loop
      if (nw === W && nh === H) return;
      if (roRaf) cancelAnimationFrame(roRaf);
      roRaf = requestAnimationFrame(() => { roRaf = 0; build(); });
    });
    ro.observe(wrap);
    const onVis = () => { running = !document.hidden; if (running) { t0 = performance.now(); raf = requestAnimationFrame(frame); } };
    document.addEventListener('visibilitychange', onVis);

    return () => {
      running = false; cancelAnimationFrame(raf); if (roRaf) cancelAnimationFrame(roRaf); ro.disconnect();
      document.removeEventListener('visibilitychange', onVis);
      if (isBackdrop) {
        window.removeEventListener('pointermove', toLocal);
      } else {
        wrap.removeEventListener('pointermove', toLocal);
        wrap.removeEventListener('pointerleave', onLeave);
        wrap.removeEventListener('pointerdown', onClick);
      }
    };
  }, [mode]);

  if (isBackdrop) {
    return <div ref={wrapRef} className="brain-backdrop" aria-hidden="true"><canvas ref={canvasRef}></canvas></div>;
  }
  return (
    <div ref={wrapRef} className="brain-canvas" style={{ height: h }}>
      <canvas ref={canvasRef}></canvas>
      <div className="bc-label"><span className="bc-dot"></span> AI Innovation Engine</div>
      <div className="bc-hint">{document.documentElement.lang === 'en' ? 'Move · click to spark ideas' : 'حرّك · انقر لتوليد الأفكار'}</div>
    </div>
  );
}

window.BrainCanvas = BrainCanvas;
