
// AgentGraph, animated SVG constellation of AI agent nodes
const { useEffect, useRef, useState, useCallback } = React;

function AgentGraph() {
  const svgRef = useRef(null);
  const animRef = useRef(null);
  const [tick, setTick] = useState(0);
  const [hovered, setHovered] = useState(null);
  const [pulsePhase, setPulsePhase] = useState(0);

  const nodes = [
    { id: 'input',    x: 80,  y: 180, label: 'Input',    sublabel: 'API / Webhook', color: '#00D9A0' },
    { id: 'memory',   x: 220, y: 80,  label: 'Memory',   sublabel: 'Vector Store',  color: '#7C5CFF' },
    { id: 'llm',      x: 320, y: 190, label: 'LLM',      sublabel: 'Claude / GPT',  color: '#00D9A0' },
    { id: 'tools',    x: 220, y: 300, label: 'Tools',    sublabel: 'APIs & Actions', color: '#FF8A4C' },
    { id: 'eval',     x: 460, y: 100, label: 'Evals',    sublabel: 'Quality Gates', color: '#7C5CFF' },
    { id: 'output',   x: 480, y: 230, label: 'Output',   sublabel: 'Response',      color: '#00D9A0' },
    { id: 'feedback', x: 370, y: 330, label: 'Feedback', sublabel: 'Loop',          color: '#FF8A4C' },
  ];

  const edges = [
    { from: 'input',  to: 'llm',      animated: true,  speed: 1.0 },
    { from: 'memory', to: 'llm',      animated: true,  speed: 0.7 },
    { from: 'llm',    to: 'tools',    animated: true,  speed: 0.9 },
    { from: 'llm',    to: 'eval',     animated: true,  speed: 0.6 },
    { from: 'llm',    to: 'output',   animated: true,  speed: 1.1 },
    { from: 'tools',  to: 'feedback', animated: true,  speed: 0.8 },
    { from: 'feedback','to': 'llm',   animated: true,  speed: 0.7 },
    { from: 'eval',   to: 'output',   animated: true,  speed: 0.5 },
    { from: 'tools',  to: 'memory',   animated: false, speed: 0.4 },
  ];

  useEffect(() => {
    let start = null;
    const loop = (ts) => {
      if (!start) start = ts;
      const t = (ts - start) / 1000;
      setPulsePhase(t);
      animRef.current = requestAnimationFrame(loop);
    };
    animRef.current = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(animRef.current);
  }, []);

  const getNode = (id) => nodes.find(n => n.id === id);

  const getEdgePath = (edge) => {
    const a = getNode(edge.from);
    const b = getNode(edge.to);
    if (!a || !b) return '';
    const mx = (a.x + b.x) / 2;
    const my = (a.y + b.y) / 2 - 20;
    return `M ${a.x} ${a.y} Q ${mx} ${my} ${b.x} ${b.y}`;
  };

  const getEdgeLength = (edge) => {
    const a = getNode(edge.from);
    const b = getNode(edge.to);
    if (!a || !b) return 100;
    return Math.hypot(b.x - a.x, b.y - a.y) * 1.2;
  };

  return (
    <div style={{ position: 'relative', width: '100%', maxWidth: 580, margin: '0 auto' }}>
      {/* Ambient glow behind graph */}
      <div style={{
        position: 'absolute', top: '50%', left: '50%',
        transform: 'translate(-50%, -50%)',
        width: 400, height: 300,
        background: 'radial-gradient(ellipse, rgba(0,217,160,0.06) 0%, rgba(124,92,255,0.05) 50%, transparent 70%)',
        pointerEvents: 'none', borderRadius: '50%',
        animation: 'glow-breathe 4s ease-in-out infinite',
      }} />

      <svg
        ref={svgRef}
        viewBox="0 0 580 420"
        style={{ width: '100%', height: 'auto', overflow: 'visible' }}
      >
        <defs>
          <filter id="glow-mint">
            <feGaussianBlur stdDeviation="3" result="blur" />
            <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
          </filter>
          <filter id="glow-violet">
            <feGaussianBlur stdDeviation="3" result="blur" />
            <feMerge><feMergeNode in="blur" /><feMergeNode in="SourceGraphic" /></feMerge>
          </filter>
          <marker id="arrowMint" markerWidth="6" markerHeight="6" refX="3" refY="3" orient="auto">
            <path d="M0,0 L0,6 L6,3 z" fill="rgba(0,217,160,0.6)" />
          </marker>
          <marker id="arrowViolet" markerWidth="6" markerHeight="6" refX="3" refY="3" orient="auto">
            <path d="M0,0 L0,6 L6,3 z" fill="rgba(124,92,255,0.6)" />
          </marker>
        </defs>

        {/* Grid lines, very subtle */}
        {[0,1,2,3,4,5].map(i => (
          <line key={`h${i}`} x1={0} y1={i*80} x2={580} y2={i*80}
            stroke="rgba(255,255,255,0.02)" strokeWidth={1} />
        ))}
        {[0,1,2,3,4,5,6,7].map(i => (
          <line key={`v${i}`} x1={i*80} y1={0} x2={i*80} y2={420}
            stroke="rgba(255,255,255,0.02)" strokeWidth={1} />
        ))}

        {/* Edges */}
        {edges.map((edge, i) => {
          const path = getEdgePath(edge);
          const len = getEdgeLength(edge);
          const fromNode = getNode(edge.from);
          const dashOffset = -(pulsePhase * edge.speed * 60) % len;
          const isHighlighted = hovered === edge.from || hovered === edge.to;
          const color = fromNode?.color === '#7C5CFF' ? '#7C5CFF' : '#00D9A0';

          return (
            <g key={i}>
              {/* Base edge */}
              <path
                d={path}
                fill="none"
                stroke={isHighlighted ? color : 'rgba(255,255,255,0.08)'}
                strokeWidth={isHighlighted ? 1.5 : 1}
                style={{ transition: 'stroke 0.3s ease' }}
              />
              {/* Animated packet */}
              {edge.animated && (
                <path
                  d={path}
                  fill="none"
                  stroke={color}
                  strokeWidth={2}
                  strokeDasharray={`10 ${len}`}
                  strokeDashoffset={dashOffset}
                  opacity={isHighlighted ? 0.9 : 0.35}
                  style={{ transition: 'opacity 0.3s ease' }}
                  markerEnd={color === '#7C5CFF' ? 'url(#arrowViolet)' : 'url(#arrowMint)'}
                />
              )}
            </g>
          );
        })}

        {/* Nodes */}
        {nodes.map((node) => {
          const isHov = hovered === node.id;
          const pulse = Math.sin(pulsePhase * 1.5 + nodes.indexOf(node) * 0.8) * 0.5 + 0.5;
          const ringR = 22 + pulse * 4;
          const ringOpacity = 0.12 + pulse * 0.08;

          return (
            <g
              key={node.id}
              transform={`translate(${node.x}, ${node.y})`}
              style={{ cursor: 'pointer' }}
              onMouseEnter={() => setHovered(node.id)}
              onMouseLeave={() => setHovered(null)}
            >
              {/* Outer pulse ring */}
              <circle r={ringR} fill="none"
                stroke={node.color} strokeWidth={1}
                opacity={isHov ? 0.4 : ringOpacity}
                style={{ transition: 'opacity 0.3s ease' }}
              />
              {/* Middle ring */}
              <circle r={17} fill="none"
                stroke={node.color} strokeWidth={isHov ? 1.5 : 0.5}
                opacity={isHov ? 0.6 : 0.2}
                style={{ transition: 'all 0.3s ease' }}
              />
              {/* Core bg */}
              <circle r={12}
                fill={isHov ? node.color + '22' : 'rgba(19,19,22,0.95)'}
                stroke={node.color}
                strokeWidth={isHov ? 1.5 : 1}
                opacity={isHov ? 1 : 0.7}
                style={{ transition: 'all 0.3s ease' }}
                filter={isHov ? `url(#glow-mint)` : undefined}
              />
              {/* Center dot */}
              <circle r={3}
                fill={node.color}
                opacity={isHov ? 1 : 0.5 + pulse * 0.3}
              />

              {/* Label */}
              <text
                y={-28}
                textAnchor="middle"
                fill={isHov ? node.color : 'rgba(245,245,247,0.7)'}
                fontSize={11}
                fontFamily="'JetBrains Mono', monospace"
                fontWeight={500}
                style={{ transition: 'fill 0.3s ease', userSelect: 'none' }}
              >
                {node.label}
              </text>
              <text
                y={-16}
                textAnchor="middle"
                fill="rgba(161,161,168,0.5)"
                fontSize={9}
                fontFamily="'JetBrains Mono', monospace"
                style={{ userSelect: 'none' }}
              >
                {node.sublabel}
              </text>
            </g>
          );
        })}
      </svg>

      {/* Live indicator */}
      <div style={{
        position: 'absolute', bottom: -8, right: 8,
        display: 'flex', alignItems: 'center', gap: 6,
        fontFamily: 'var(--font-mono)', fontSize: 10,
        color: 'var(--text-tertiary)',
      }}>
        <span style={{
          width: 6, height: 6, borderRadius: '50%',
          background: '#00D9A0',
          boxShadow: '0 0 6px #00D9A0',
          animation: 'pulse-dot 2s ease-in-out infinite',
        }} />
        system live
      </div>

      <style>{`
        @keyframes glow-breathe {
          0%, 100% { opacity: 0.7; transform: translate(-50%,-50%) scale(1); }
          50% { opacity: 1; transform: translate(-50%,-50%) scale(1.08); }
        }
        @keyframes pulse-dot {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.4; }
        }
      `}</style>
    </div>
  );
}

Object.assign(window, { AgentGraph });
