/* ============================================================
   routing.jsx — the routing diagram engine
   Hub (本机 Agent) + nodes + animated wires.
   ============================================================ */
const { useState: _us, useEffect: _ue, useRef: _ur } = React;

/* cubic bezier path from hub -> node, horizontal ease */
function wirePath(hx, hy, nx, ny) {
  const mx = hx + (nx - hx) * 0.55;
  return `M ${hx} ${hy} C ${mx} ${hy}, ${hx + (nx - hx) * 0.45} ${ny}, ${nx} ${ny}`;
}

function RoutingStage({
  hub = { label: "本机 Agent", sub: "AgentPilot", brand: "localagent" },
  hubPos = { x: 21, y: 50 },
  nodes = [],
  lit = [],          // ids with active wire + flow
  done = [],         // ids showing a ✓ (serial)
  dim = [],          // ids grayed/filtered (converge)
  converge = false,  // reverse flow direction (nodes -> hub)
  inIds = null,      // per-node inward flow (node -> hub); overrides `converge` when set
  sideLabels = null, // { left, right } captions framing the in/out direction
  running = false,   // hub pulsing
  hubState = "idle", // idle | working | synth
  showHubRings = true,
  children,
}) {
  const [ref, { w, h }] = useSize();
  const litSet = new Set(lit), doneSet = new Set(done), dimSet = new Set(dim);
  const inSet = inIds ? new Set(inIds) : null;

  const px = (p) => (p / 100) * w;
  const py = (p) => (p / 100) * h;
  const hx = px(hubPos.x), hy = py(hubPos.y);
  const nodeR = w <= 600 ? 20 : 25;
  const nodeAnchor = (nx, ny) => ({
    x: nx + (nx < hx ? nodeR : -nodeR),
    y: ny,
  });

  return (
    <div className="route-stage" ref={ref}>
      {/* soft backdrop grid */}
      <div className="route-grid" />

      {/* directional framing: sources flow in from the left, results go out to the right */}
      {sideLabels && (
        <>
          <div className="route-side left"><span className="rs-arrow">→</span>{sideLabels.left}</div>
          <div className="route-side right">{sideLabels.right}<span className="rs-arrow">→</span></div>
        </>
      )}

      {/* wires */}
      <svg className="route-wires" width={w} height={h} viewBox={`0 0 ${w} ${h}`}>
        <defs>
          <filter id="wireGlow" x="-30%" y="-30%" width="160%" height="160%">
            <feGaussianBlur stdDeviation="2.4" result="b" />
            <feMerge><feMergeNode in="b" /><feMergeNode in="SourceGraphic" /></feMerge>
          </filter>
          {/* 彗星核：中心实、边缘 alpha→0 的柔光，叠 wireGlow 拖出流光感 */}
          <radialGradient id="cometCore" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="var(--accent)" stopOpacity="1" />
            <stop offset="55%" stopColor="var(--accent)" stopOpacity=".85" />
            <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
          </radialGradient>
        </defs>
        {w > 0 && nodes.map((n) => {
          const nx = px(n.x), ny = py(n.y);
          const end = nodeAnchor(nx, ny);
          const d = wirePath(hx, hy, end.x, end.y);
          const isLit = litSet.has(n.id);
          const isDim = dimSet.has(n.id);
          const inward = inSet ? inSet.has(n.id) : converge;   // node -> hub when inward
          const kp = inward ? "1;0" : "0;1";                   // path starts at hub
          return (
            <g key={n.id} className={"wire" + (isDim ? " dim" : "") + (inward ? " in" : " out")}>
              <path className="wire-base" d={d} />
              <path id={"wire-" + n.id} className={"wire-lit" + (isLit ? " on" : "")}
                    d={d} pathLength="1" />
              {/* 流光统一为柔光小点，不再用短线段沿路径扫动；inward 时反向流（node→hub）。 */}
              {isLit && (
                <circle className="wire-dot" r="3.2">
                  <animateMotion dur="2.6s" repeatCount="indefinite"
                                 keyPoints={kp} keyTimes="0;1" calcMode="linear">
                    <mpath href={"#wire-" + n.id} />
                  </animateMotion>
                </circle>
              )}
            </g>
          );
        })}
      </svg>

      {/* hub */}
      <div className={"route-hub " + hubState + (running ? " running" : "")}
           style={{ left: hx, top: hy }}>
        <div className="hub-core">
          <BrandTile brand={hub.brand || "localagent"} size={34} radius={10} soft={false} />
          <div className="hub-text">
            <span className="hub-label">{hub.label}</span>
            <span className="hub-sub">{hub.sub}</span>
          </div>
        </div>
        {showHubRings && running && <span className="hub-ring" />}
        {showHubRings && running && <span className="hub-ring r2" />}
      </div>

      {/* nodes */}
      {nodes.map((n) => {
        const isLit = litSet.has(n.id), isDone = doneSet.has(n.id), isDim = dimSet.has(n.id);
        return (
          <div key={n.id}
               className={"route-node" + (isLit ? " lit" : "") + (isDone ? " done" : "") + (isDim ? " dim" : "")}
               style={{ left: px(n.x), top: py(n.y) }}>
            <BrandTile brand={n.brand} size={50} glow={isLit} />
            <div className="rn-meta">
              <span className="rn-label">{n.label}</span>
              {n.tag && <span className={"rn-tag t-" + (n.tagTone || "neutral")}>{n.tag}</span>}
            </div>
            {isDone && <span className="rn-check"><DoneTick /></span>}
          </div>
        );
      })}

      {children}
    </div>
  );
}

Object.assign(window, { RoutingStage, wirePath });
