/* TENACITY — Workflow orchestration visual */
const { useState, useEffect, useMemo, useRef } = React;

const NODES = [
  // input row
  { id: "email",    x: 110, y: 130, label: "Input",   title: "Inbox",        meta: "imap · gmail",   icon: "mail" },
  { id: "form",     x: 110, y: 250, label: "Input",   title: "Web Form",     meta: "stripe · webhook", icon: "form" },
  { id: "crm",      x: 110, y: 370, label: "Input",   title: "CRM Event",    meta: "hubspot · salesforce", icon: "crm" },

  // reasoning core
  { id: "router",   x: 360, y: 250, label: "Routing",   title: "Intent Router", meta: "policy v3.2",  icon: "router" },
  { id: "agent",    x: 600, y: 130, label: "AI Agent",  title: "Research Agent", meta: "claude · supervised", icon: "agent" },
  { id: "ops",      x: 600, y: 250, label: "AI Agent",  title: "Ops Agent",      meta: "fine-tuned · v4", icon: "agent" },
  { id: "qa",       x: 600, y: 370, label: "Guardrail", title: "QA Harness",     meta: "evals · 99.4%",   icon: "shield" },

  // action row
  { id: "slack",    x: 860, y: 130, label: "Action", title: "Notify Team",   meta: "slack · channel", icon: "send" },
  { id: "db",       x: 860, y: 250, label: "Action", title: "Write to DW",   meta: "snowflake",       icon: "db" },
  { id: "trigger",  x: 860, y: 370, label: "Action", title: "Trigger Flow",  meta: "n8n · zapier",    icon: "spark" },
];

const EDGES = [
  { from: "email",  to: "router" },
  { from: "form",   to: "router" },
  { from: "crm",    to: "router" },
  { from: "router", to: "agent" },
  { from: "router", to: "ops" },
  { from: "router", to: "qa" },
  { from: "agent",  to: "slack" },
  { from: "ops",    to: "db" },
  { from: "qa",     to: "trigger" },
  { from: "ops",    to: "trigger" },
];

// Active path cycles around the system
const PATHS = [
  ["email", "router", "agent", "slack"],
  ["form", "router", "ops", "db"],
  ["crm", "router", "qa", "trigger"],
  ["form", "router", "ops", "trigger"],
];

function Icon({ name }) {
  const props = { width: 14, height: 14, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round", strokeLinejoin: "round" };
  switch (name) {
    case "mail":   return <svg {...props}><rect x="3" y="5" width="18" height="14" rx="2"/><path d="M3 7l9 6 9-6"/></svg>;
    case "form":   return <svg {...props}><rect x="4" y="4" width="16" height="16" rx="2"/><path d="M8 10h8M8 14h5"/></svg>;
    case "crm":    return <svg {...props}><circle cx="12" cy="9" r="3"/><path d="M5 20c1-3.5 4-5 7-5s6 1.5 7 5"/></svg>;
    case "router": return <svg {...props}><circle cx="12" cy="12" r="3"/><path d="M12 2v4M12 18v4M2 12h4M18 12h4M5 5l3 3M19 5l-3 3M5 19l3-3M19 19l-3-3"/></svg>;
    case "agent":  return <svg {...props}><rect x="5" y="6" width="14" height="12" rx="3"/><circle cx="9" cy="12" r="1.2"/><circle cx="15" cy="12" r="1.2"/><path d="M12 2v4"/></svg>;
    case "shield": return <svg {...props}><path d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6z"/><path d="M9 12l2 2 4-4"/></svg>;
    case "send":   return <svg {...props}><path d="M22 2L11 13"/><path d="M22 2l-7 20-4-9-9-4z"/></svg>;
    case "db":     return <svg {...props}><ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.7 3.6 3 8 3s8-1.3 8-3V5"/><path d="M4 11v6c0 1.7 3.6 3 8 3s8-1.3 8-3v-6"/></svg>;
    case "spark":  return <svg {...props}><path d="M12 3v6M12 15v6M3 12h6M15 12h6M5.6 5.6l4.2 4.2M14.2 14.2l4.2 4.2M5.6 18.4l4.2-4.2M14.2 9.8l4.2-4.2"/></svg>;
    default:       return null;
  }
}

function Workflow() {
  const VW = 1000, VH = 480;
  const [active, setActive] = useState(0);
  const [tick, setTick] = useState(0);

  // Cycle the active path
  useEffect(() => {
    const id = setInterval(() => setActive((a) => (a + 1) % PATHS.length), 2600);
    return () => clearInterval(id);
  }, []);

  // For continuous packet animation
  useEffect(() => {
    let raf;
    const start = performance.now();
    const loop = (t) => {
      setTick(t - start);
      raf = requestAnimationFrame(loop);
    };
    raf = requestAnimationFrame(loop);
    return () => cancelAnimationFrame(raf);
  }, []);

  const byId = useMemo(() => Object.fromEntries(NODES.map((n) => [n.id, n])), []);
  const activePath = PATHS[active];
  const activeEdgeSet = useMemo(() => {
    const s = new Set();
    for (let i = 0; i < activePath.length - 1; i++) s.add(activePath[i] + "->" + activePath[i + 1]);
    return s;
  }, [activePath]);
  const activeNodes = new Set(activePath);

  return (
    <div className="workflow-stage">
      <div className="workflow-legend">
        <div className="row"><span className="dot" style={{background:"oklch(0.78 0.17 235)"}}/>Input signals</div>
        <div className="row"><span className="dot" style={{background:"oklch(0.85 0.13 220)"}}/>Reasoning layer</div>
        <div className="row"><span className="dot" style={{background:"oklch(0.78 0.17 145)"}}/>Action surface</div>
      </div>
      <div className="workflow-status">
        <span className="dot"/>Live · routing active
      </div>

      {/* Edges */}
      <svg viewBox={`0 0 ${VW} ${VH}`} preserveAspectRatio="xMidYMid meet">
        <defs>
          <linearGradient id="edge" x1="0" x2="1">
            <stop offset="0%" stopColor="oklch(0.78 0.17 235)" stopOpacity="0"/>
            <stop offset="50%" stopColor="oklch(0.85 0.13 220)" stopOpacity="0.9"/>
            <stop offset="100%" stopColor="oklch(0.78 0.17 235)" stopOpacity="0"/>
          </linearGradient>
          <radialGradient id="packet">
            <stop offset="0%" stopColor="oklch(0.95 0.05 220)"/>
            <stop offset="50%" stopColor="oklch(0.78 0.17 235)"/>
            <stop offset="100%" stopColor="oklch(0.78 0.17 235)" stopOpacity="0"/>
          </radialGradient>
          <filter id="glow" x="-30%" y="-30%" width="160%" height="160%">
            <feGaussianBlur stdDeviation="2.4" result="b"/>
            <feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
          </filter>
        </defs>

        {EDGES.map((e, i) => {
          const a = byId[e.from], b = byId[e.to];
          const key = e.from + "->" + e.to;
          const on = activeEdgeSet.has(key);
          const cx = (a.x + b.x) / 2;
          // gentle curve
          const cpY = (a.y + b.y) / 2 + (a.y === b.y ? -20 : 0);
          const d = `M ${a.x} ${a.y} Q ${cx} ${cpY} ${b.x} ${b.y}`;
          return (
            <g key={i}>
              <path
                d={d}
                fill="none"
                stroke={on ? "oklch(0.78 0.17 235)" : "rgba(140, 165, 210, 0.18)"}
                strokeWidth={on ? 1.4 : 0.8}
                strokeDasharray={on ? "0" : "3 4"}
                style={{ filter: on ? "url(#glow)" : "none", transition: "all 0.5s ease" }}
              />
            </g>
          );
        })}

        {/* Animated packets along the active path */}
        {activePath.slice(0, -1).map((from, idx) => {
          const a = byId[from], b = byId[activePath[idx + 1]];
          const cx = (a.x + b.x) / 2;
          const cpY = (a.y + b.y) / 2 + (a.y === b.y ? -20 : 0);
          // progress 0..1, offset per segment
          const phase = ((tick / 1800) + idx * 0.18) % 1;
          // Quadratic Bezier interpolation
          const t = phase;
          const px = (1 - t) * (1 - t) * a.x + 2 * (1 - t) * t * cx + t * t * b.x;
          const py = (1 - t) * (1 - t) * a.y + 2 * (1 - t) * t * cpY + t * t * b.y;
          return (
            <circle key={idx} cx={px} cy={py} r="6" fill="url(#packet)" style={{ filter: "url(#glow)" }}/>
          );
        })}
      </svg>

      {/* Nodes */}
      {NODES.map((n) => (
        <div
          key={n.id}
          className={"node-card" + (activeNodes.has(n.id) ? " active" : "")}
          style={{ left: `${(n.x / VW) * 100}%`, top: `${(n.y / VH) * 100}%` }}
        >
          <div className="label">{n.label}</div>
          <div className="title"><Icon name={n.icon}/>{n.title}</div>
          <div className="meta">{n.meta}</div>
        </div>
      ))}
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById("workflow-root"));
root.render(<Workflow/>);
