// AgentArchViz, cinematic multi-agent system visualization
// Shows a REAL agentic architecture: Orchestrator + sub-agents + tools + memory + feedback loops
// Adapts cleanly to dark AND light mode via CSS variables
const { useRef: useAaRef, useEffect: useAaEffect, useState: useAaState } = React;

// Node layout, orchestrator at center, agents around it, tools on right, inputs on left
const NODES = [
  // Inputs
  { id: 'trigger',     x: 40,  y: 180, label: 'Trigger',      sub: 'API / Webhook',  type: 'input',   color: '#00D9A0' },

  // Core agents
  { id: 'orch',        x: 200, y: 180, label: 'Orchestrator',  sub: 'Routes tasks',   type: 'agent',   color: '#00D9A0' },
  { id: 'classifier',  x: 340, y: 80,  label: 'Classifier',    sub: 'Intent + scope', type: 'agent',   color: '#7C5CFF' },
  { id: 'memory',      x: 340, y: 180, label: 'Memory',        sub: 'Vector recall',  type: 'agent',   color: '#7C5CFF' },
  { id: 'toolcaller',  x: 340, y: 280, label: 'Tool Caller',   sub: 'API executor',   type: 'agent',   color: '#FF8A4C' },

  // Tools / external
  { id: 'crm',         x: 480, y: 50,  label: 'CRM',           sub: 'Salesforce/HubSpot', type: 'tool', color: '#6E6E76' },
  { id: 'calendar',    x: 480, y: 130, label: 'Calendar',      sub: 'Booking API',    type: 'tool',    color: '#6E6E76' },
  { id: 'kb',          x: 480, y: 210, label: 'Knowledge',     sub: 'Vector DB',      type: 'tool',    color: '#6E6E76' },
  { id: 'email',       x: 480, y: 290, label: 'Email/SMS',     sub: 'Twilio / SES',   type: 'tool',    color: '#6E6E76' },

  // Validator + output
  { id: 'validator',   x: 340, y: 360, label: 'Validator',     sub: 'Evals + QA',     type: 'agent',   color: '#FBBF24' },
  { id: 'respond',     x: 540, y: 370, label: 'Response',      sub: 'Delivered',      type: 'output',  color: '#00D9A0' },
];

const EDGES = [
  { from: 'trigger',    to: 'orch',        dir: 'forward',  speed: 1.0 },
  { from: 'orch',       to: 'classifier',  dir: 'forward',  speed: 0.8 },
  { from: 'orch',       to: 'memory',      dir: 'forward',  speed: 0.9 },
  { from: 'orch',       to: 'toolcaller',  dir: 'forward',  speed: 0.7 },
  { from: 'classifier', to: 'crm',         dir: 'forward',  speed: 0.6 },
  { from: 'classifier', to: 'calendar',    dir: 'forward',  speed: 0.6 },
  { from: 'memory',     to: 'kb',          dir: 'bidirect', speed: 0.7 },
  { from: 'toolcaller', to: 'email',       dir: 'forward',  speed: 0.8 },
  { from: 'toolcaller', to: 'calendar',    dir: 'forward',  speed: 0.5 },
  { from: 'orch',       to: 'validator',   dir: 'forward',  speed: 0.6 },
  { from: 'validator',  to: 'respond',     dir: 'forward',  speed: 0.9 },
  { from: 'validator',  to: 'orch',        dir: 'feedback', speed: 0.4 },  // feedback loop
  { from: 'classifier', to: 'orch',        dir: 'feedback', speed: 0.5 },
];

const EVENTS = [
  'Booking request · Med Spa',
  'Contract query · Law Firm',
  'Lead follow-up · Real Estate',
  'Invoice review · CPA Firm',
  'Support ticket · E-commerce',
  'Missed call · Healthcare',
];

function AgentArchViz({ theme }) {
  const rafRef = useAaRef(null);
  const startRef = useAaRef(null);
  const [tick, setTick] = useAaState(0);
  const [eventIdx, setEventIdx] = useAaState(0);
  const [activeNodes, setActiveNodes] = useAaState(new Set(['trigger']));
  const isDark = theme === 'dark';

  useAaEffect(() => {
    const CYCLE = 4;
    const ACTIVATE_SEQ = [
      ['trigger'],
      ['trigger', 'orch'],
      ['trigger', 'orch', 'classifier', 'memory', 'toolcaller'],
      ['orch', 'classifier', 'memory', 'toolcaller', 'crm', 'calendar', 'kb', 'email'],
      ['memory', 'toolcaller', 'kb', 'email', 'validator'],
      ['validator', 'respond'],
    ];

    const loop = (ts) => {
      if (!startRef.current) startRef.current = ts;
      const t = (ts - startRef.current) / 1000;
      setTick(t);
      const cycleT = (t % CYCLE) / CYCLE;
      const seqIdx = Math.min(Math.floor(cycleT * ACTIVATE_SEQ.length), ACTIVATE_SEQ.length - 1);
      setActiveNodes(new Set(ACTIVATE_SEQ[seqIdx]));
      setEventIdx(Math.floor(t / CYCLE) % EVENTS.length);
      rafRef.current = requestAnimationFrame(loop);
    };
    rafRef.current = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(rafRef.current);
  }, []);

  const getN = (id) => NODES.find(n => n.id === id);

  const edgePath = (edge) => {
    const a = getN(edge.from), b = getN(edge.to);
    if (!a || !b) return '';
    const dx = b.x - a.x, dy = b.y - a.y;
    // Curved paths for feedback, straight for others
    if (edge.dir === 'feedback') {
      return `M ${a.x} ${a.y} C ${a.x - 30} ${a.y + 40} ${b.x - 30} ${b.y + 40} ${b.x} ${b.y}`;
    }
    const cx = (a.x + b.x) / 2, cy = (a.y + b.y) / 2 - 15;
    return `M ${a.x} ${a.y} Q ${cx} ${cy} ${b.x} ${b.y}`;
  };

  const isEdgeActive = (edge) =>
    activeNodes.has(edge.from) && activeNodes.has(edge.to);

  const nodeColor = (node) => {
    if (node.type === 'tool') return isDark ? '#3D3D45' : '#D0D0E0';
    return node.color;
  };

  const labelColor = isDark ? 'rgba(245,245,247,0.85)' : 'rgba(8,8,16,0.9)';
  const subLabelColor = isDark ? 'rgba(161,161,168,0.6)' : 'rgba(30,30,50,0.65)';
  const gridColor = isDark ? 'rgba(255,255,255,0.025)' : 'rgba(0,0,0,0.05)';
  const edgeBase = isDark ? 'rgba(255,255,255,0.06)' : 'rgba(0,0,0,0.1)';

  return (
    <div style={{
      position: 'relative',
      width: '100%',
      userSelect: 'none',
    }}>
      <svg
        viewBox="0 0 580 430"
        style={{ width: '100%', height: 'auto', overflow: 'visible', display: 'block' }}
      >
        <defs>
          {NODES.map(n => (
            <filter key={n.id} id={`glow-aa-${n.id}`}>
              <feGaussianBlur stdDeviation="5" result="blur"/>
              <feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
            </filter>
          ))}
          <marker id="aa-arrow-mint" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto">
            <path d="M0,0 L6,3 L0,6 Z" fill="rgba(0,217,160,0.7)"/>
          </marker>
          <marker id="aa-arrow-violet" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto">
            <path d="M0,0 L6,3 L0,6 Z" fill="rgba(124,92,255,0.7)"/>
          </marker>
          <marker id="aa-arrow-warm" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto">
            <path d="M0,0 L6,3 L0,6 Z" fill="rgba(255,138,76,0.7)"/>
          </marker>
          <radialGradient id="aa-bg-glow" cx="50%" cy="45%" r="50%">
            <stop offset="0%" stopColor={isDark ? 'rgba(0,217,160,0.04)' : 'rgba(0,150,110,0.06)'}/>
            <stop offset="60%" stopColor={isDark ? 'rgba(124,92,255,0.03)' : 'rgba(72,40,204,0.04)'}/>
            <stop offset="100%" stopColor="rgba(0,0,0,0)"/>
          </radialGradient>
        </defs>

        {/* Ambient background glow */}
        <ellipse cx="290" cy="200" rx="260" ry="180" fill="url(#aa-bg-glow)"/>

        {/* Subtle grid */}
        {Array.from({length:7}, (_,i) => (
          <line key={`h${i}`} x1={0} y1={i*70} x2={580} y2={i*70} stroke={gridColor} strokeWidth={0.8}/>
        ))}
        {Array.from({length:9}, (_,i) => (
          <line key={`v${i}`} x1={i*72} y1={0} x2={i*72} y2={430} stroke={gridColor} strokeWidth={0.8}/>
        ))}

        {/* Section labels */}
        <text x={200} y={22} textAnchor="middle" fill={isDark ? 'rgba(0,217,160,0.35)' : 'rgba(0,120,80,0.4)'}
          fontSize={8} fontFamily="JetBrains Mono, monospace" letterSpacing="0.1em">AGENT CLUSTER</text>
        <rect x={130} y={26} width={140} height={1} fill={isDark ? 'rgba(0,217,160,0.15)' : 'rgba(0,120,80,0.15)'}/>

        <text x={480} y={22} textAnchor="middle" fill={isDark ? 'rgba(255,138,76,0.35)' : 'rgba(180,80,0,0.4)'}
          fontSize={8} fontFamily="JetBrains Mono, monospace" letterSpacing="0.1em">TOOLS</text>
        <rect x={430} y={26} width={100} height={1} fill={isDark ? 'rgba(255,138,76,0.15)' : 'rgba(180,80,0,0.15)'}/>

        {/* Edges */}
        {EDGES.map((edge, i) => {
          const path = edgePath(edge);
          const active = isEdgeActive(edge);
          const fromNode = getN(edge.from);
          const ec = fromNode?.type === 'tool' ? '#6E6E76' : fromNode?.color || '#00D9A0';

          return (
            <g key={i}>
              {/* Base edge */}
              <path d={path} fill="none"
                stroke={active ? ec : edgeBase}
                strokeWidth={active ? 1.5 : 0.8}
                strokeDasharray={edge.dir === 'feedback' ? '4 4' : 'none'}
                style={{ transition: 'stroke 0.5s ease, stroke-width 0.4s ease' }}
              />
              {/* Moving packet */}
              {active && (
                <circle r={3} fill={ec} opacity={0.9}>
                  <animateMotion
                    dur={`${1.2 / (edge.speed || 1)}s`}
                    repeatCount="indefinite"
                    path={path}
                  />
                </circle>
              )}
            </g>
          );
        })}

        {/* Nodes */}
        {NODES.map(node => {
          const isActive = activeNodes.has(node.id);
          const isTool = node.type === 'tool';
          const pulse = Math.sin(tick * 1.8 + NODES.indexOf(node) * 0.7) * 0.5 + 0.5;
          const nc = isTool
            ? (isDark ? '#3D3D45' : '#C8C8D8')
            : node.color;

          return (
            <g key={node.id} transform={`translate(${node.x}, ${node.y})`}>
              {/* Outer pulse ring, only for active non-tool nodes */}
              {isActive && !isTool && (
                <circle
                  r={20 + pulse * 5}
                  fill="none"
                  stroke={nc}
                  strokeWidth={0.8}
                  opacity={0.15 + pulse * 0.1}
                />
              )}

              {/* Background circle */}
              <circle
                r={isTool ? 10 : 14}
                fill={isActive
                  ? (isDark ? `${nc}1A` : `${nc}25`)
                  : (isDark ? 'rgba(28,28,33,0.9)' : 'rgba(240,240,248,0.9)')}
                stroke={nc}
                strokeWidth={isActive ? 1.5 : (isTool ? 0.8 : 1)}
                opacity={isActive ? 1 : (isTool ? 0.5 : 0.4)}
                filter={isActive && !isTool ? `url(#glow-aa-${node.id})` : undefined}
                style={{ transition: 'all 0.4s ease' }}
              />

              {/* Center dot */}
              <circle r={isTool ? 2 : 3}
                fill={isActive ? nc : (isDark ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.15)')}
                style={{ transition: 'fill 0.3s ease' }}
              />

              {/* Label */}
              <text
                y={isTool ? -16 : -22}
                textAnchor="middle"
                fill={isActive ? (isTool ? (isDark ? '#A1A1A8' : '#2A2A3A') : nc) : (isDark ? 'rgba(245,245,247,0.35)' : 'rgba(10,10,18,0.7)')}
                fontSize={isTool ? 9 : 10}
                fontFamily="JetBrains Mono, monospace"
                fontWeight={600}
                style={{ transition: 'fill 0.4s ease', userSelect: 'none' }}
              >{node.label}</text>

              {/* Sub-label */}
              <text
                y={isTool ? 22 : 26}
                textAnchor="middle"
                fill={isActive ? subLabelColor : (isDark ? 'rgba(161,161,168,0.2)' : 'rgba(30,30,50,0.45)')}
                fontSize={8}
                fontFamily="JetBrains Mono, monospace"
                style={{ transition: 'fill 0.4s ease', userSelect: 'none' }}
              >{node.sub}</text>
            </g>
          );
        })}

        {/* Live event label */}
        <text x={20} y={415}
          fill={isDark ? 'rgba(0,217,160,0.5)' : 'rgba(0,120,80,0.5)'}
          fontSize={9} fontFamily="JetBrains Mono, monospace" letterSpacing="0.06em"
        >▶ {EVENTS[eventIdx]}</text>

        {/* Live indicator */}
        <circle cx={560} cy={415} r={4}
          fill={isDark ? '#00D9A0' : '#007A5A'}
          style={{ animation: 'aa-pulse 2s ease infinite' }}
        />
        <text x={550} y={415}
          textAnchor="end"
          fill={isDark ? 'rgba(0,217,160,0.6)' : 'rgba(0,120,80,0.6)'}
          fontSize={9} fontFamily="JetBrains Mono, monospace"
        >live</text>
      </svg>

      <style>{`
        @keyframes aa-pulse { 0%,100%{opacity:1;r:4} 50%{opacity:0.4;r:3} }
      `}</style>
    </div>
  );
}

Object.assign(window, { AgentArchViz });
