// Three hero variants for loboLab.
//   1. NeuralMesh   — animated network of agents (default — user explicitly asked for this)
//   2. WolfHowling  — wolf silhouette howling at a glowing moon, particles + faint constellation
//   3. DataStreams  — vertical streams of orange data points + rotating ring of agent labels
//
// All three share a layered structure:
//   - <canvas> for the background motion
//   - <svg> overlays for fixed glyphs
//   - children (the hero content) sit on top
//
// They listen to `intensity` ('low' | 'med' | 'high') and scale particle counts accordingly.

const HERO_PALETTE = {
  ink: "#0A0B10",
  inkSoft: "#0F1118",
  orange: "#F08A2B",
  orangeBright: "#FF9D3F",
  orangeGlow: "rgba(240, 138, 43, 0.55)",
  slate: "#6B7A91",
  white: "#F5F6F8",
};

// ─────────────────────────────────────────────────────────────────────────────
// Hook: requestAnimationFrame loop with cleanup. Pauses when tab hidden.
function useRaf(callback, deps = []) {
  React.useEffect(() => {
    let raf, last = performance.now();
    const tick = (now) => {
      const dt = Math.min(0.05, (now - last) / 1000);
      last = now;
      callback(dt, now / 1000);
      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, deps);
}

// Resize a canvas to its CSS size × DPR. Returns [w,h] in CSS px.
function fitCanvas(cv) {
  const dpr = Math.min(window.devicePixelRatio || 1, 2);
  const r = cv.getBoundingClientRect();
  cv.width = Math.round(r.width * dpr);
  cv.height = Math.round(r.height * dpr);
  const ctx = cv.getContext("2d");
  ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
  return [r.width, r.height, ctx];
}

// ─────────────────────────────────────────────────────────────────────────────
// 1. NEURAL MESH — drifting nodes with proximity edges; orange "active" pulses
//    travel along edges. The wolf eye-shape sits subtly behind everything.
function NeuralMesh({ intensity = "med" }) {
  const cvRef = React.useRef(null);
  const stateRef = React.useRef({ nodes: [], pulses: [], w: 0, h: 0 });
  const COUNT = intensity === "high" ? 110 : intensity === "low" ? 45 : 75;
  const LINK_DIST = 150;

  React.useEffect(() => {
    const cv = cvRef.current;
    if (!cv) return;
    const init = () => {
      const [w, h] = fitCanvas(cv);
      const nodes = Array.from({ length: COUNT }, () => ({
        x: Math.random() * w, y: Math.random() * h,
        vx: (Math.random() - 0.5) * 14, vy: (Math.random() - 0.5) * 14,
        r: 1 + Math.random() * 1.8,
        active: Math.random() < 0.12,
      }));
      stateRef.current = { nodes, pulses: [], w, h };
    };
    init();
    const onR = () => init();
    window.addEventListener("resize", onR);
    return () => window.removeEventListener("resize", onR);
  }, [COUNT]);

  useRaf((dt, t) => {
    const cv = cvRef.current; if (!cv) return;
    const ctx = cv.getContext("2d");
    const { nodes, pulses, w, h } = stateRef.current;
    if (!w) return;

    ctx.clearRect(0, 0, w, h);

    // soft radial vignette anchored slightly above center
    const grad = ctx.createRadialGradient(w * 0.5, h * 0.4, 0, w * 0.5, h * 0.4, Math.max(w, h) * 0.7);
    grad.addColorStop(0, "rgba(240,138,43,0.06)");
    grad.addColorStop(1, "rgba(10,11,16,0)");
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, w, h);

    // move nodes
    for (const n of nodes) {
      n.x += n.vx * dt;
      n.y += n.vy * dt;
      if (n.x < 0 || n.x > w) n.vx *= -1;
      if (n.y < 0 || n.y > h) n.vy *= -1;
    }

    // edges
    ctx.lineWidth = 1;
    for (let i = 0; i < nodes.length; i++) {
      for (let j = i + 1; j < nodes.length; j++) {
        const a = nodes[i], b = nodes[j];
        const dx = a.x - b.x, dy = a.y - b.y;
        const d = Math.hypot(dx, dy);
        if (d < LINK_DIST) {
          const alpha = (1 - d / LINK_DIST) * 0.22;
          // tint edges connecting two active nodes orange
          const isHot = a.active && b.active;
          ctx.strokeStyle = isHot
            ? `rgba(240,138,43,${alpha * 1.8})`
            : `rgba(120,140,170,${alpha})`;
          ctx.beginPath();
          ctx.moveTo(a.x, a.y);
          ctx.lineTo(b.x, b.y);
          ctx.stroke();
        }
      }
    }

    // nodes
    for (const n of nodes) {
      if (n.active) {
        ctx.fillStyle = HERO_PALETTE.orange;
        ctx.shadowBlur = 12;
        ctx.shadowColor = HERO_PALETTE.orangeGlow;
      } else {
        ctx.fillStyle = "rgba(180,195,220,0.55)";
        ctx.shadowBlur = 0;
      }
      ctx.beginPath();
      ctx.arc(n.x, n.y, n.r + (n.active ? 1.5 : 0), 0, Math.PI * 2);
      ctx.fill();
    }
    ctx.shadowBlur = 0;

    // pulses traveling between random pairs of active nodes
    if (Math.random() < (intensity === "high" ? 0.18 : intensity === "low" ? 0.04 : 0.09)) {
      const actives = nodes.filter(n => n.active);
      if (actives.length > 1) {
        const a = actives[Math.floor(Math.random() * actives.length)];
        const b = actives[Math.floor(Math.random() * actives.length)];
        if (a !== b) pulses.push({ a, b, p: 0, life: 1.2 });
      }
    }
    for (let i = pulses.length - 1; i >= 0; i--) {
      const pl = pulses[i];
      pl.p += dt / pl.life;
      if (pl.p >= 1) { pulses.splice(i, 1); continue; }
      const x = pl.a.x + (pl.b.x - pl.a.x) * pl.p;
      const y = pl.a.y + (pl.b.y - pl.a.y) * pl.p;
      ctx.fillStyle = HERO_PALETTE.orangeBright;
      ctx.shadowBlur = 18;
      ctx.shadowColor = HERO_PALETTE.orangeGlow;
      ctx.beginPath(); ctx.arc(x, y, 2.5, 0, Math.PI * 2); ctx.fill();
      ctx.shadowBlur = 0;
    }
  }, [intensity]);

  return (
    <div className="hero-bg">
      <canvas ref={cvRef} className="hero-canvas" />
      <div className="hero-grid" aria-hidden="true" />
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// 2. WOLF HOWLING — user's idea. Lone wolf silhouette on a ridge, head tilted up,
//    against a glowing orange moon. Embers/particles drift up. Subtle constellation
//    behind the moon connects faintly to suggest "agents".
function WolfHowling({ intensity = "med" }) {
  const cvRef = React.useRef(null);
  const stateRef = React.useRef({ embers: [], stars: [], w: 0, h: 0 });
  const EMBER_COUNT = intensity === "high" ? 90 : intensity === "low" ? 30 : 55;
  const STAR_COUNT = intensity === "high" ? 80 : intensity === "low" ? 30 : 55;

  React.useEffect(() => {
    const cv = cvRef.current; if (!cv) return;
    const init = () => {
      const [w, h] = fitCanvas(cv);
      const embers = Array.from({ length: EMBER_COUNT }, () => ({
        x: Math.random() * w,
        y: h * 0.6 + Math.random() * h * 0.4,
        vy: -8 - Math.random() * 22,
        vx: (Math.random() - 0.5) * 6,
        r: 0.6 + Math.random() * 1.6,
        a: 0.3 + Math.random() * 0.7,
        life: 1,
      }));
      const stars = Array.from({ length: STAR_COUNT }, () => ({
        x: Math.random() * w, y: Math.random() * h * 0.6,
        r: 0.4 + Math.random() * 1.4,
        tw: Math.random() * Math.PI * 2,
      }));
      stateRef.current = { embers, stars, w, h };
    };
    init();
    const onR = () => init();
    window.addEventListener("resize", onR);
    return () => window.removeEventListener("resize", onR);
  }, [EMBER_COUNT, STAR_COUNT]);

  useRaf((dt, t) => {
    const cv = cvRef.current; if (!cv) return;
    const ctx = cv.getContext("2d");
    const { embers, stars, w, h } = stateRef.current;
    if (!w) return;

    // Transparent canvas — the background image is rendered by the parent <div>.
    // We only draw atmospheric overlays (stars, constellation lines, embers and a
    // soft orange glow around the moon area) on top of the image.
    ctx.clearRect(0, 0, w, h);

    // Soft orange aura over the moon area of the image (upper-center)
    const mx = w * 0.5, my = h * 0.42, mr = Math.min(w, h) * 0.45;
    const moonGlow = ctx.createRadialGradient(mx, my, 0, mx, my, mr);
    moonGlow.addColorStop(0, "rgba(255,170,80,0.18)");
    moonGlow.addColorStop(0.5, "rgba(240,138,43,0.06)");
    moonGlow.addColorStop(1, "rgba(240,138,43,0)");
    ctx.fillStyle = moonGlow;
    ctx.fillRect(0, 0, w, h);

    // Stars (mostly upper half so they don't sit on the ridge)
    for (const s of stars) {
      s.tw += dt * 2;
      const tw = 0.5 + 0.5 * Math.sin(s.tw + s.x);
      ctx.fillStyle = `rgba(255,210,140,${0.25 + tw * 0.45})`;
      ctx.beginPath(); ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2); ctx.fill();
    }

    // Faint constellation lines connecting nearby stars (the "agents" thread)
    ctx.strokeStyle = "rgba(240,138,43,0.14)";
    ctx.lineWidth = 0.6;
    for (let i = 0; i < stars.length; i++) {
      for (let j = i + 1; j < Math.min(i + 4, stars.length); j++) {
        const a = stars[i], b = stars[j];
        const d = Math.hypot(a.x - b.x, a.y - b.y);
        if (d < 130) {
          ctx.beginPath(); ctx.moveTo(a.x, a.y); ctx.lineTo(b.x, b.y); ctx.stroke();
        }
      }
    }

    // Embers
    for (const e of embers) {
      e.x += e.vx * dt;
      e.y += e.vy * dt;
      e.life -= dt * 0.18;
      if (e.life <= 0 || e.y < h * 0.1) {
        e.x = Math.random() * w;
        e.y = h * 0.85 + Math.random() * h * 0.1;
        e.life = 1;
        e.vy = -8 - Math.random() * 22;
      }
      const a = e.a * Math.max(0, e.life);
      ctx.fillStyle = `rgba(255,160,70,${a})`;
      ctx.shadowBlur = 8; ctx.shadowColor = "rgba(255,150,60,0.6)";
      ctx.beginPath(); ctx.arc(e.x, e.y, e.r, 0, Math.PI * 2); ctx.fill();
    }
    ctx.shadowBlur = 0;
  }, [intensity]);

  return (
    <div className="hero-bg hero-bg-wolf">
      <div className="wolf-photo" aria-hidden="true" />
      <canvas ref={cvRef} className="hero-canvas" />
      <div className="wolf-vignette" aria-hidden="true" />
    </div>
  );
}

// (kept for reference — no longer used now that the wolf hero uses a real photo)
function drawWolfSilhouette(ctx, cx, cy, size) {
  ctx.save();
  ctx.translate(cx, cy);
  ctx.scale(size / 100, size / 100);
  ctx.fillStyle = "#000";
  ctx.beginPath();
  // body (sitting), legs, tail, then neck stretched up, head tilted
  ctx.moveTo(-50, 0);          // tail base on ground
  ctx.quadraticCurveTo(-65, -10, -55, -28);   // tail curving up
  ctx.quadraticCurveTo(-50, -38, -40, -30);
  ctx.lineTo(-30, -22);                       // back
  ctx.quadraticCurveTo(-10, -32, 0, -38);     // shoulders rising
  ctx.quadraticCurveTo(8, -50, 12, -68);      // neck up
  ctx.quadraticCurveTo(14, -82, 22, -88);     // head base
  ctx.lineTo(28, -94);                        // ear back
  ctx.lineTo(32, -86);                        // between ears
  ctx.lineTo(38, -94);                        // ear front
  ctx.quadraticCurveTo(46, -88, 50, -78);     // forehead/snout up
  ctx.lineTo(58, -76);                        // snout tip (open mouth howl)
  ctx.lineTo(50, -70);                        // jaw
  ctx.lineTo(42, -68);
  ctx.quadraticCurveTo(34, -64, 28, -58);     // jaw under
  ctx.quadraticCurveTo(20, -45, 18, -30);     // chest down
  ctx.lineTo(22, -10);                        // front leg
  ctx.lineTo(28, 0);
  ctx.lineTo(10, 0);                          // ground
  ctx.lineTo(8, -10);
  ctx.lineTo(2, 0);
  ctx.lineTo(-20, 0);
  ctx.lineTo(-22, -8);
  ctx.lineTo(-30, 0);
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}

// ─────────────────────────────────────────────────────────────────────────────
// 3. DATA STREAMS — vertical falling streams of orange characters/dots
//    (matrix-vibe but cleaner) + a slow ring of agent labels orbiting.
function DataStreams({ intensity = "med" }) {
  const cvRef = React.useRef(null);
  const stateRef = React.useRef({ cols: [], w: 0, h: 0 });
  const FONT_SIZE = 14;

  React.useEffect(() => {
    const cv = cvRef.current; if (!cv) return;
    const init = () => {
      const [w, h] = fitCanvas(cv);
      const colCount = Math.floor(w / FONT_SIZE);
      const cols = Array.from({ length: colCount }, (_, i) => ({
        x: i * FONT_SIZE,
        y: -Math.random() * h,
        speed: 40 + Math.random() * (intensity === "high" ? 140 : intensity === "low" ? 50 : 90),
        chars: [],
        bright: Math.random() < 0.18,
      }));
      stateRef.current = { cols, w, h };
    };
    init();
    const onR = () => init();
    window.addEventListener("resize", onR);
    return () => window.removeEventListener("resize", onR);
  }, [intensity]);

  const GLYPHS = "01<>{}/[]αβ∑Δ◆◇•※⌬⎈⌗".split("");

  useRaf((dt) => {
    const cv = cvRef.current; if (!cv) return;
    const ctx = cv.getContext("2d");
    const { cols, w, h } = stateRef.current;
    if (!w) return;

    // trail fade
    ctx.fillStyle = "rgba(8,9,14,0.18)";
    ctx.fillRect(0, 0, w, h);

    ctx.font = `${FONT_SIZE}px ui-monospace, "JetBrains Mono", monospace`;
    ctx.textBaseline = "top";

    for (const c of cols) {
      c.y += c.speed * dt;
      if (c.y > h + 200) {
        c.y = -Math.random() * 300;
        c.bright = Math.random() < 0.18;
      }
      // draw a column of ~22 glyphs trailing upward
      for (let i = 0; i < 22; i++) {
        const yy = c.y - i * FONT_SIZE;
        if (yy < -FONT_SIZE || yy > h) continue;
        const fade = 1 - i / 22;
        const ch = GLYPHS[(Math.floor(yy * 0.5) + i + Math.floor(c.x)) % GLYPHS.length];
        if (i === 0) {
          ctx.fillStyle = c.bright ? `rgba(255,200,140,${fade})` : `rgba(255,180,90,${fade})`;
        } else {
          const a = fade * (c.bright ? 0.7 : 0.35);
          ctx.fillStyle = c.bright ? `rgba(240,138,43,${a})` : `rgba(110,130,160,${a})`;
        }
        ctx.fillText(ch, c.x, yy);
      }
    }
  }, [intensity]);

  return (
    <div className="hero-bg">
      <canvas ref={cvRef} className="hero-canvas" />
      <div className="hero-grid" aria-hidden="true" />
    </div>
  );
}

// Expose to window for the main app
Object.assign(window, { NeuralMesh, WolfHowling, DataStreams, HERO_PALETTE });
