// 2D topology — logical network map
function Topology({ nodes, onSelect }) {
  const [hover, setHover] = React.useState(null);

  // layout: columns by group
  const layout = React.useMemo(() => {
    const W = 1600, H = Math.max(800, Math.ceil(Math.max(...window.GROUPS.map(g => nodes.filter(n => n.group === g).length)) / 2) * 70 + 280);
    const positions = {};
    window.GROUPS.forEach((group, gi) => {
      const list = nodes.filter(n => n.group === group);
      const colX = 200 + gi * 280;
      list.forEach((n, i) => {
        const col = i % 2;
        const row = Math.floor(i / 2);
        positions[n.id] = {
          x: colX + col * 110,
          y: 200 + row * 62,
        };
      });
    });
    return { positions, W, H };
  }, [nodes]);

  const statusColor = (s) => s === 'ok' ? 'var(--ok)' : s === 'crit' ? 'var(--crit)' : (s === 'maint' || s === 'warn') ? 'var(--warn)' : 'var(--off)';

  return (
    <div className="topo-wrap" style={{overflow:'auto'}}>
      <svg viewBox={`0 0 ${layout.W} ${layout.H}`} width={layout.W} height={layout.H} style={{display:'block', minWidth:'100%'}}>
        <defs>
          <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto">
            <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--accent-dim)"/>
          </marker>
        </defs>

        {/* group columns */}
        {window.GROUPS.map((group, gi) => {
          const list = nodes.filter(n => n.group === group);
          if (!list.length) return null;
          const x = 180 + gi * 280;
          const h = Math.ceil(list.length / 2) * 62 + 70;
          return (
            <g key={group}>
              <rect x={x} y={170} width={240} height={h} fill="rgba(20, 30, 45, 0.35)" stroke="var(--border-2)" strokeDasharray="4 4" />
              <text x={x + 12} y={190} fill="var(--text-faint)" fontSize="11" fontFamily="var(--mono)" letterSpacing="2">
                {group.toUpperCase()} · {list.length}
              </text>
            </g>
          );
        })}

        {/* Viewer (top node) */}
        <g>
          <circle cx="70" cy="60" r="22" fill="rgba(50, 200, 230, 0.1)" stroke="var(--accent)" />
          <text x="70" y="64" textAnchor="middle" fill="var(--accent)" fontSize="10" fontFamily="var(--mono)">WAN</text>
          <text x="70" y="95" textAnchor="middle" fill="var(--text-faint)" fontSize="9" fontFamily="var(--mono)">monitoring · probes</text>
        </g>

        {/* Cloudflare edge */}
        <g>
          <rect x="30" y="180" width="120" height="50" fill="rgba(50, 200, 230, 0.08)" stroke="var(--accent)" />
          <text x="90" y="202" textAnchor="middle" fill="var(--accent)" fontSize="11" fontFamily="var(--mono)" fontWeight="600">CF-EDGE</text>
          <text x="90" y="216" textAnchor="middle" fill="var(--text-faint)" fontSize="9" fontFamily="var(--mono)">cloudflare</text>
        </g>
        <line x1="70" y1="82" x2="90" y2="180" stroke="var(--accent-dim)" strokeWidth="1" markerEnd="url(#arrow)" />

        {/* edges from CF-EDGE to group first node */}
        {window.GROUPS.map((group, gi) => {
          const list = nodes.filter(n => n.group === group);
          const first = list[0];
          if (!first) return null;
          const p = layout.positions[first.id];
          return (
            <path key={group + '-edge'}
              d={`M 150 205 C ${(150 + p.x)/2} 205, ${(150 + p.x)/2} ${p.y}, ${p.x - 40} ${p.y}`}
              fill="none" stroke="var(--border-3)" strokeWidth="0.8" opacity="0.6" />
          );
        })}

        {/* Nodes */}
        {nodes.map(n => {
          const p = layout.positions[n.id];
          if (!p) return null;
          const col = statusColor(n.status);
          const isHover = hover === n.id;
          const label = n.displayName.length > 18 ? n.displayName.slice(0, 16) + '…' : n.displayName;
          return (
            <g key={n.id}
               transform={`translate(${p.x}, ${p.y})`}
               style={{cursor: 'pointer'}}
               onMouseEnter={() => setHover(n.id)}
               onMouseLeave={() => setHover(null)}
               onClick={() => onSelect(n)}>
              {n.status === 'crit' && (
                <circle r="22" fill={col} opacity="0.25">
                  <animate attributeName="r" values="16;28;16" dur="1.5s" repeatCount="indefinite"/>
                  <animate attributeName="opacity" values="0.45;0;0.45" dur="1.5s" repeatCount="indefinite"/>
                </circle>
              )}
              <rect x="-42" y="-16" width="84" height="32"
                fill={n.status === 'off' ? 'var(--surface)' : col}
                opacity={n.status === 'off' ? 1 : 0.15}
                stroke={col} strokeWidth={isHover ? 1.8 : 0.8} rx="1" />
              <circle cx="36" cy="-10" r="2.5" fill={col}>
                {n.status === 'crit' && <animate attributeName="opacity" values="1;0.2;1" dur="1s" repeatCount="indefinite"/>}
              </circle>
              <text y="-2" textAnchor="middle" fill="var(--text)" fontSize="9" fontFamily="var(--mono)">
                {label}
              </text>
              <text y="10" textAnchor="middle" fill="var(--text-faint)" fontSize="8" fontFamily="var(--mono)">
                {n.status === 'off' ? 'timeout' : `${n.latency.toFixed(0)}ms · ${n.httpCode}`}
              </text>
              {isHover && (
                <g>
                  <rect x="-100" y="-55" width="200" height="34" fill="rgba(10,14,20,0.96)" stroke="var(--accent-dim)" rx="2"/>
                  <text y="-40" textAnchor="middle" fill="var(--text)" fontSize="10" fontFamily="var(--mono)">{n.hostname}</text>
                  <text y="-28" textAnchor="middle" fill="var(--text-faint)" fontSize="9" fontFamily="var(--mono)">{n.protocol}:{n.port} · TLS {n.sslDaysLeft}d</text>
                </g>
              )}
            </g>
          );
        })}
      </svg>

      <div className="threed-hud" style={{top: 12, left: 12, right: 12, position:'absolute'}}>
        <div className="hud-panel">
          <h4>Topology · logical</h4>
          <div className="hud-row"><span>groups</span><span>{window.GROUPS.length}</span></div>
          <div className="hud-row"><span>endpoints</span><span>{nodes.length}</span></div>
          <div className="hud-row"><span>probes from</span><span>monitoring agent</span></div>
        </div>
        <div className="hud-panel">
          <h4>Legend</h4>
          <div className="hud-row"><span className="dot ok"/><span>up · 200-299</span></div>
          <div className="hud-row"><span className="dot crit"/><span>down · 5xx / 4xx</span></div>
          <div className="hud-row"><span className="dot maint"/><span>maintenance</span></div>
          <div className="hud-row"><span className="dot off"/><span>timeout</span></div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Topology });
