// NeuroForge — animation primitives & visualizations
const { useEffect, useRef, useState } = React;

// ============ Hero Forge Background — flowing energy mesh ============
function HeroNetwork() {
  const canvasRef = useRef(null);
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    let raf, dpr = window.devicePixelRatio || 1;
    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();
    window.addEventListener('resize', resize);

    // Build a triangular mesh of nodes — fixed positions, breathing
    const nodes = [];
    const COLS = 9, ROWS = 7;
    for (let row = 0; row < ROWS; row++) {
      for (let col = 0; col < COLS; col++) {
        const xn = col / (COLS - 1);
        const yn = row / (ROWS - 1);
        // jitter so it doesn't look like a perfect grid
        const jx = (Math.sin(col * 12.9898 + row * 78.233) * 43758.5453 % 1) * 0.5 - 0.25;
        const jy = (Math.sin(col * 39.346 + row * 11.135) * 23421.631 % 1) * 0.5 - 0.25;
        nodes.push({
          xn: xn + jx * 0.06,
          yn: yn + jy * 0.06,
          phase: Math.random() * Math.PI * 2,
          freq: 0.8 + Math.random() * 0.6,
        });
      }
    }

    // Build edges — connect each node to 2-3 nearest
    const edges = [];
    for (let i = 0; i < nodes.length; i++) {
      const dists = [];
      for (let j = 0; j < nodes.length; j++) {
        if (i === j) continue;
        const dx = nodes[i].xn - nodes[j].xn;
        const dy = nodes[i].yn - nodes[j].yn;
        dists.push({ j, d: Math.hypot(dx, dy) });
      }
      dists.sort((a, b) => a.d - b.d);
      const conns = 2 + (i % 2);
      for (let k = 0; k < conns; k++) {
        const j = dists[k].j;
        const key = i < j ? `${i}-${j}` : `${j}-${i}`;
        if (!edges.find(e => e.key === key)) {
          edges.push({ a: i, b: j, key, len: dists[k].d });
        }
      }
    }

    // Energy pulses traveling along edges
    const pulses = [];
    const COLORS = ['#00e0ff', '#a855f7', '#22f0d5', '#ec4899'];
    const spawnPulse = () => {
      const e = edges[Math.floor(Math.random() * edges.length)];
      const dir = Math.random() < 0.5 ? 1 : -1;
      pulses.push({
        edge: e,
        t: dir > 0 ? 0 : 1,
        speed: (0.004 + Math.random() * 0.006) * dir,
        color: COLORS[Math.floor(Math.random() * COLORS.length)],
        life: 1,
      });
    };
    for (let i = 0; i < 14; i++) spawnPulse();

    let t0 = performance.now();

    const tick = (now) => {
      const dt = (now - t0) / 16.67; t0 = now;
      ctx.clearRect(0, 0, W, H);

      // Compute current node positions (with breathing)
      const T = now * 0.001;
      const positions = nodes.map(n => {
        const breathe = Math.sin(T * n.freq + n.phase) * 4;
        return {
          x: n.xn * W + breathe,
          y: n.yn * H + breathe * 0.6,
        };
      });

      // Draw edges
      edges.forEach(e => {
        const a = positions[e.a], b = positions[e.b];
        const grad = ctx.createLinearGradient(a.x, a.y, b.x, b.y);
        grad.addColorStop(0, 'rgba(0,224,255,0.06)');
        grad.addColorStop(0.5, 'rgba(168,85,247,0.10)');
        grad.addColorStop(1, 'rgba(0,224,255,0.06)');
        ctx.strokeStyle = grad;
        ctx.lineWidth = 0.8;
        ctx.beginPath();
        ctx.moveTo(a.x, a.y);
        ctx.lineTo(b.x, b.y);
        ctx.stroke();
      });

      // Draw pulses (with trail)
      for (let i = pulses.length - 1; i >= 0; i--) {
        const p = pulses[i];
        p.t += p.speed * dt;
        if (p.t > 1 || p.t < 0) {
          pulses.splice(i, 1);
          continue;
        }
        const a = positions[p.edge.a], b = positions[p.edge.b];
        // trail
        for (let k = 0; k < 6; k++) {
          const tt = p.t - (k * 0.04 * Math.sign(p.speed));
          if (tt < 0 || tt > 1) continue;
          const x = a.x + (b.x - a.x) * tt;
          const y = a.y + (b.y - a.y) * tt;
          const alpha = (1 - k / 6) * 0.7;
          ctx.beginPath();
          ctx.fillStyle = p.color;
          ctx.globalAlpha = alpha;
          ctx.shadowColor = p.color;
          ctx.shadowBlur = k === 0 ? 14 : 0;
          ctx.arc(x, y, k === 0 ? 2.2 : 1.4 - k * 0.15, 0, Math.PI * 2);
          ctx.fill();
        }
        ctx.globalAlpha = 1;
        ctx.shadowBlur = 0;
      }

      // Draw nodes (small, dim — they're just anchors)
      positions.forEach((p, i) => {
        const breathing = 0.4 + Math.sin(T * nodes[i].freq + nodes[i].phase) * 0.3;
        ctx.beginPath();
        ctx.fillStyle = `rgba(0,224,255,${0.15 + breathing * 0.15})`;
        ctx.arc(p.x, p.y, 1.4, 0, Math.PI * 2);
        ctx.fill();
      });

      // Spawn new pulses to maintain count
      while (pulses.length < 14 && Math.random() < 0.4) spawnPulse();

      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => { cancelAnimationFrame(raf); window.removeEventListener('resize', resize); };
  }, []);
  return <canvas ref={canvasRef} className="hero-canvas" />;
}

// ============ Animated Counter ============
function Counter({ to, suffix = '', duration = 1800, decimals = 0 }) {
  const [val, setVal] = useState(0);
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    let started = false;
    const obs = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting && !started) {
        started = true;
        const start = performance.now();
        const tick = (now) => {
          const t = Math.min(1, (now - start) / duration);
          const eased = 1 - Math.pow(1 - t, 3);
          setVal(to * eased);
          if (t < 1) requestAnimationFrame(tick);
        };
        requestAnimationFrame(tick);
      }
    }, { threshold: 0.5 });
    obs.observe(el);
    return () => obs.disconnect();
  }, [to, duration]);
  const formatted = decimals > 0 ? val.toFixed(decimals) : Math.round(val).toLocaleString();
  return <span ref={ref}>{formatted}{suffix}</span>;
}

// ============ Reveal on scroll ============
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('.reveal');
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) e.target.classList.add('in');
      });
    }, { threshold: 0.12 });
    els.forEach(el => obs.observe(el));
    return () => obs.disconnect();
  });
}

// ============ Card mouse spotlight ============
function useCardSpotlight() {
  useEffect(() => {
    const handler = (e) => {
      const card = e.target.closest('.card');
      if (!card) return;
      const r = card.getBoundingClientRect();
      card.style.setProperty('--mx', `${e.clientX - r.left}px`);
      card.style.setProperty('--my', `${e.clientY - r.top}px`);
    };
    document.addEventListener('mousemove', handler);
    return () => document.removeEventListener('mousemove', handler);
  });
}

// ============ Brand Mark ============
function BrandMark() {
  return (
    <svg viewBox="0 0 32 32" fill="none">
      <defs>
        <linearGradient id="bg" x1="0" y1="0" x2="32" y2="32">
          <stop offset="0%" stopColor="#00e0ff"/>
          <stop offset="100%" stopColor="#a855f7"/>
        </linearGradient>
      </defs>
      <path d="M6 6 L6 26 M6 6 L26 26 M26 6 L26 26" stroke="url(#bg)" strokeWidth="2.4" strokeLinecap="round"/>
      <circle cx="6" cy="6" r="2.6" fill="#00e0ff"/>
      <circle cx="26" cy="6" r="2.6" fill="#a855f7"/>
      <circle cx="6" cy="26" r="2.6" fill="#22f0d5"/>
      <circle cx="26" cy="26" r="2.6" fill="#ec4899"/>
      <circle cx="16" cy="16" r="3" fill="#fff"/>
    </svg>
  );
}

// ============ Capability visual: agent graph mini ============
function MiniAgentGraph() {
  return (
    <svg viewBox="0 0 320 140" style={{width:'100%', height:'100%'}}>
      <defs>
        <radialGradient id="mg-glow" cx="50%" cy="50%">
          <stop offset="0%" stopColor="#00e0ff" stopOpacity="0.25"/>
          <stop offset="100%" stopColor="#00e0ff" stopOpacity="0"/>
        </radialGradient>
      </defs>
      <rect width="320" height="140" fill="url(#mg-glow)"/>
      {/* edges */}
      {[
        [160,30, 80,75], [160,30, 240,75],
        [80,75, 50,115], [80,75, 130,115],
        [240,75, 200,115], [240,75, 270,115],
        [80,75, 240,75]
      ].map(([x1,y1,x2,y2], i) => (
        <line key={i} x1={x1} y1={y1} x2={x2} y2={y2} stroke="rgba(0,224,255,0.4)" strokeWidth="1">
          <animate attributeName="stroke-opacity" values="0.2;0.7;0.2" dur={`${2+i*0.3}s`} repeatCount="indefinite"/>
        </line>
      ))}
      {/* moving packet */}
      <circle r="2.5" fill="#22f0d5">
        <animateMotion dur="3s" repeatCount="indefinite" path="M 160 30 L 80 75 L 130 115"/>
      </circle>
      <circle r="2.5" fill="#ec4899">
        <animateMotion dur="2.5s" repeatCount="indefinite" path="M 160 30 L 240 75 L 270 115"/>
      </circle>
      {/* nodes */}
      <circle cx="160" cy="30" r="6" fill="#a855f7"><animate attributeName="r" values="6;8;6" dur="2s" repeatCount="indefinite"/></circle>
      <circle cx="80" cy="75" r="4.5" fill="#00e0ff"/>
      <circle cx="240" cy="75" r="4.5" fill="#00e0ff"/>
      <circle cx="50" cy="115" r="3.5" fill="#22f0d5"/>
      <circle cx="130" cy="115" r="3.5" fill="#22f0d5"/>
      <circle cx="200" cy="115" r="3.5" fill="#22f0d5"/>
      <circle cx="270" cy="115" r="3.5" fill="#22f0d5"/>
    </svg>
  );
}

// ============ Capability visual: RL chart ============
function MiniRLChart() {
  const points = Array.from({length: 40}, (_, i) => {
    const x = (i / 39) * 320;
    const noise = Math.sin(i * 0.7) * 8;
    const y = 120 - (i * 2.4) + noise + (i > 25 ? -8 : 0);
    return `${x},${Math.max(20, Math.min(120, y))}`;
  }).join(' ');
  return (
    <svg viewBox="0 0 320 140" style={{width:'100%', height:'100%'}}>
      <defs>
        <linearGradient id="rl-grad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#00e0ff" stopOpacity="0.4"/>
          <stop offset="100%" stopColor="#00e0ff" stopOpacity="0"/>
        </linearGradient>
      </defs>
      {[0,1,2,3].map(i => <line key={i} x1="0" x2="320" y1={20+i*30} y2={20+i*30} stroke="rgba(255,255,255,0.04)"/>)}
      <polygon points={`0,140 ${points} 320,140`} fill="url(#rl-grad)"/>
      <polyline points={points} fill="none" stroke="#00e0ff" strokeWidth="1.5"/>
      <circle r="3" fill="#22f0d5">
        <animateMotion dur="4s" repeatCount="indefinite" path={`M ${points.split(' ').slice(0,-1).map(p => p).join(' L ')}`} />
      </circle>
    </svg>
  );
}

// ============ Capability visual: cyber threat scope ============
function MiniCyberScope() {
  return (
    <svg viewBox="0 0 320 140" style={{width:'100%', height:'100%'}}>
      <defs>
        <radialGradient id="cyb-r" cx="50%" cy="50%">
          <stop offset="0%" stopColor="#ef4444" stopOpacity="0.25"/>
          <stop offset="100%" stopColor="#ef4444" stopOpacity="0"/>
        </radialGradient>
      </defs>
      <rect width="320" height="140" fill="url(#cyb-r)"/>
      {/* concentric */}
      {[20,40,60].map(r => (
        <circle key={r} cx="160" cy="70" r={r} fill="none" stroke="rgba(239,68,68,0.25)" strokeDasharray="3 4"/>
      ))}
      {/* sweep */}
      <line x1="160" y1="70" x2="160" y2="10" stroke="#ef4444" strokeWidth="1.5" opacity="0.7">
        <animateTransform attributeName="transform" type="rotate" from="0 160 70" to="360 160 70" dur="3s" repeatCount="indefinite"/>
      </line>
      {/* threats */}
      {[
        [120,40,'#ff8c42'],[200,55,'#ef4444'],[180,95,'#fbbf24'],[140,90,'#4ade80'],[210,30,'#fbbf24']
      ].map(([x,y,c],i) => (
        <circle key={i} cx={x} cy={y} r="3" fill={c}>
          <animate attributeName="opacity" values="1;0.3;1" dur={`${1.5+i*0.4}s`} repeatCount="indefinite"/>
        </circle>
      ))}
      <circle cx="160" cy="70" r="4" fill="#fff"/>
    </svg>
  );
}

// ============ Capability visual: model layers ============
function MiniLLM() {
  return (
    <svg viewBox="0 0 320 140" style={{width:'100%', height:'100%'}}>
      {[0,1,2,3].map(layer => (
        <g key={layer}>
          {Array.from({length: 8}).map((_, i) => (
            <rect key={i} x={20 + i*36} y={20 + layer*28} width="24" height="14" rx="2"
              fill={`rgba(${layer===1 || layer===2 ? '168,85,247' : '0,224,255'},${0.3 + (i%3)*0.2})`}>
              <animate attributeName="opacity" values={`0.3;${0.6+(i%3)*0.15};0.3`} dur={`${2+i*0.2}s`} repeatCount="indefinite" begin={`${layer*0.1}s`}/>
            </rect>
          ))}
        </g>
      ))}
    </svg>
  );
}

// ============ Capability visual: HITL ============
function MiniHITL() {
  return (
    <svg viewBox="0 0 320 140" style={{width:'100%', height:'100%'}}>
      <circle cx="80" cy="70" r="22" fill="none" stroke="#00e0ff" strokeWidth="1.5"/>
      <circle cx="80" cy="70" r="5" fill="#00e0ff"/>
      <text x="80" y="105" textAnchor="middle" fontSize="9" fill="#5b6080" fontFamily="JetBrains Mono">HUMAN</text>

      <circle cx="240" cy="70" r="22" fill="none" stroke="#a855f7" strokeWidth="1.5"/>
      <circle cx="240" cy="70" r="5" fill="#a855f7"/>
      <text x="240" y="105" textAnchor="middle" fontSize="9" fill="#5b6080" fontFamily="JetBrains Mono">AGENT</text>

      <path d="M 102 60 Q 160 30 218 60" fill="none" stroke="rgba(0,224,255,0.5)" strokeWidth="1" strokeDasharray="3 3"/>
      <path d="M 218 80 Q 160 110 102 80" fill="none" stroke="rgba(168,85,247,0.5)" strokeWidth="1" strokeDasharray="3 3"/>
      <circle r="3" fill="#22f0d5"><animateMotion dur="2s" repeatCount="indefinite" path="M 102 60 Q 160 30 218 60"/></circle>
      <circle r="3" fill="#ec4899"><animateMotion dur="2s" repeatCount="indefinite" path="M 218 80 Q 160 110 102 80"/></circle>
    </svg>
  );
}

// ============ Capability visual: telemetry ============
function MiniTelemetry() {
  return (
    <svg viewBox="0 0 320 140" style={{width:'100%', height:'100%'}}>
      {Array.from({length: 32}).map((_, i) => {
        const h = 20 + ((Math.sin(i*0.7) + 1) * 30) + (i%5)*6;
        return (
          <rect key={i} x={8 + i*9.5} y={130 - h} width="6" height={h} rx="1"
            fill={i%4===0 ? '#a855f7' : '#00e0ff'} opacity={0.4 + (i%5)*0.1}>
            <animate attributeName="height" values={`${h};${h+15};${h}`} dur={`${1.5 + (i%4)*0.3}s`} repeatCount="indefinite"/>
            <animate attributeName="y" values={`${130-h};${130-h-15};${130-h}`} dur={`${1.5 + (i%4)*0.3}s`} repeatCount="indefinite"/>
          </rect>
        );
      })}
    </svg>
  );
}

window.NF = {
  HeroNetwork, Counter, useReveal, useCardSpotlight, BrandMark,
  MiniAgentGraph, MiniRLChart, MiniCyberScope, MiniLLM, MiniHITL, MiniTelemetry
};
