/* global React, ReactDOM, AgentCanvas, DetailPanel, Icon */
/* ============================================================
   Central de Agentes — App shell
   ============================================================ */
const Icon = window.Icon, AgentCanvas = window.AgentCanvas, DetailPanel = window.DetailPanel, PipelineView = window.PipelineView;
const { RunsModule, ApprovalsModule, AlertsModule, ModelsModule, McpsModule, RoiModule, SettingsModule, NewAgentModal, McpCredentialsModal } = window;
const NODE_W_APP = 316, NODE_H_APP = 344;
const sleepApp = (ms) => new Promise((r) => setTimeout(r, ms));

// ---------- THEME ----------
function themeFor(dark) {
  if (dark) return {
    // paleta NN do standalone: preto neutro + accent periwinkle
    pageBg: "#000000", gridDot: "rgba(174,203,224,.14)",
    cardBg: "#141416", cardBorder: "#242427", cardShadow: "0 24px 46px rgba(0,0,0,.5)",
    ink: "#ffffff", ink2: "rgba(207,207,207,.62)", ink3: "rgba(207,207,207,.5)",
    chipBg: "rgba(255,255,255,.03)", chipBorder: "#1f1f22",
    statBg: "rgba(255,255,255,.02)", trayBg: "rgba(255,255,255,.02)",
    edge: "rgba(174,203,224,.22)", edgeDash: "rgba(174,203,224,.26)", edgeLabelBg: "#0c0c0e",
    panelBg: "#0a0a0c", panelBorder: "#242427", railBg: "#060607",
  };
  return {
    pageBg: "#eaeef0", gridDot: "rgba(13,56,59,.11)",
    cardBg: "#ffffff", cardBorder: "rgba(13,56,59,.12)", cardShadow: "0 12px 32px rgba(13,56,59,.10)",
    ink: "#0d383b", ink2: "#4d5e5f", ink3: "#8a9394",
    chipBg: "#f2f6f6", chipBorder: "rgba(13,56,59,.10)",
    statBg: "#f5f8f8", trayBg: "#f7fafa",
    edge: "rgba(13,56,59,.20)", edgeDash: "rgba(13,56,59,.20)", edgeLabelBg: "#ffffff",
    panelBg: "#ffffff", panelBorder: "rgba(13,56,59,.12)", railBg: "#0d383b",
  };
}

const TWEAK_DEFAULTS = { theme: "dark", edgeLabels: true, mcpMotion: true, grid: true };
const POS_KEY = "central-agentes-pos-v2";
const TWK_KEY = "central-agentes-tweaks-v3"; // v3: dark vira padrão (estilo NN); descarta tema claro salvo
const VIEW_KEY = "central-agentes-view-v2";
const COMPANY_KEY = "central-agentes-company-v1";
const EMPTY_AGENTS = [];

// ---------- COMPANIES (multi-tenant) ----------
const COMPANIES = {
  nnstudio: { id: "nnstudio", name: "NN.ai", sub: "Grupo NN.ai · Contábil", tagline: "NN.ai · camada agêntica · 5 esteiras" },
  viveo: { id: "viveo", name: "Viveo", sub: "Viveo · Saúde", tagline: "Viveo · workspace novo · nenhuma esteira ainda" },
};
const COMPANY_LIST = Object.values(COMPANIES);

// ---------- TENANT BRANDS ----------
// NN owns the product chrome; each tenant injects its accent ramp + rail color.
// These override the --brand-teal-* tokens on the .app container, re-tinting
// every CTA / active state without touching component code.
const BRANDS = {
  nnstudio: { rail: "#0d383b", navActive: "#1a494d", avatar: "linear-gradient(135deg,#1a494d,#8fb3d4)",
    accent700: "#7ea3cc", accent600: "#8fb3d4", accent500: "#9bbcd9", accent400: "#1fa0aa", accentSoft: "#E6F4F5" },
  viveo: { rail: "#0F4B55", navActive: "#13626c", avatar: "linear-gradient(135deg,#0F4B55,#13818f)",
    accent700: "#0c3b43", accent600: "#0F4B55", accent500: "#13818f", accent400: "#6EE1DC", accentSoft: "#E6F7F6" },
};

// nn.ai platform signature — wordmark, white on the dark rail.
function NNMark({ height, onDark }) {
  return <img src="assets/nn-logo.svg" alt="nn.ai" style={{ height, width: "auto", objectFit: "contain", filter: onDark ? "brightness(0) invert(1)" : "none", opacity: onDark ? 0.9 : 1 }} />;
}

// company brand mark — turquoise tile for Viveo, deep-teal/white for NN.ai
function CompanyMark({ id, size, onDark }) {
  const r = Math.round(size * 0.26);
  if (id === "viveo") {
    return (
      <span style={{ width: size, height: size, borderRadius: r, background: "#6EE1DC", display: "grid", placeItems: "center", flex: `0 0 ${size}px` }}>
        <img src="assets/viveo-favicon.png" alt="Viveo" style={{ width: Math.round(size * 0.6), height: Math.round(size * 0.6), objectFit: "contain" }} />
      </span>
    );
  }
  if (onDark) return <NNMark height={Math.max(16, Math.round(size * 0.42))} onDark />;
  return (
    <span style={{ width: size, height: size, borderRadius: r, background: "#0d383b", display: "grid", placeItems: "center", flex: `0 0 ${size}px` }}>
      <NNMark height={Math.max(16, Math.round(size * 0.34))} onDark />
    </span>
  );
}

// empty-workspace state shown for a company with no agents yet (Viveo)
function ViveoEmptyState({ nav, t, dark, onNew }) {
  const M = {
    esteiras: { icon: "git-branch", title: "Nenhuma esteira ainda", desc: "Este é o workspace da Viveo, ainda em branco. Crie o primeiro agente para começar a montar a esteira." },
    execucoes: { icon: "history", title: "Sem execuções", desc: "As execuções dos agentes da Viveo aparecerão aqui assim que houver atividade." },
    aprovacoes: { icon: "check", title: "Nada para aprovar", desc: "Quando um agente da Viveo exigir liberação humana, a solicitação aparece aqui." },
    alertas: { icon: "bell", title: "Nenhum alerta", desc: "Incidentes e alertas dos agentes da Viveo serão listados aqui." },
    modelos: { icon: "cpu", title: "Nenhum modelo em uso", desc: "Os modelos de IA usados pelos agentes da Viveo aparecerão aqui." },
    mcps: { icon: "plug", title: "Nenhum MCP conectado", desc: "Conecte ferramentas e integrações (MCPs) aos agentes da Viveo." },
    roi: { icon: "trending-up", title: "Sem dados de ROI", desc: "O retorno e o custo dos agentes da Viveo aparecerão aqui." },
  };
  const m = M[nav] || M.esteiras;
  return (
    <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center", padding: 24 }}>
      <div style={{ textAlign: "center", maxWidth: 430 }}>
        <div style={{ width: 84, height: 84, margin: "0 auto 20px", borderRadius: 24, background: dark ? "rgba(110,225,220,.12)" : "#E6F7F6", border: `1px dashed ${dark ? "rgba(110,225,220,.34)" : "#9bdcd8"}`, display: "grid", placeItems: "center" }}>
          <Icon name={m.icon} size={30} stroke={1.8} style={{ color: dark ? "#6EE1DC" : "#0F4B55" }} />
        </div>
        <div style={{ fontFamily: "var(--font-brand)", fontSize: 21, fontWeight: 700, color: t.ink, marginBottom: 8 }}>{m.title}</div>
        <div style={{ fontSize: 13, color: t.ink2, lineHeight: 1.55, textWrap: "pretty", marginBottom: 22 }}>{m.desc}</div>
        <button onClick={onNew} className="btn-primary lg" style={{ background: "#0F4B55" }}>
          <Icon name="plus" size={15} stroke={2} /> Criar primeiro agente
        </button>
      </div>
    </div>
  );
}

function App() {
  const { AGENTS, EDGES, fmtTokens, fmtBRL, fmtNum, STATUS } = window.AgentData;

  const [agents, setAgents] = React.useState(() => {
    let saved = {};
    try { saved = JSON.parse(localStorage.getItem(POS_KEY) || "{}"); } catch (e) {}
    return AGENTS.map((a) => ({ ...a, pos: saved[a.id] || a.pos, recent: [...a.recent] }));
  });
  const [tweaks, setTweaks] = React.useState(() => {
    try { return { ...TWEAK_DEFAULTS, ...JSON.parse(localStorage.getItem(TWK_KEY) || "{}") }; } catch (e) { return TWEAK_DEFAULTS; }
  });
  const [showTweaks, setShowTweaks] = React.useState(false);
  const [selectedId, setSelectedId] = React.useState(null);
  const [running, setRunning] = React.useState(false);
  const [nodeRun, setNodeRun] = React.useState({});
  const [mode, setMode] = React.useState(() => localStorage.getItem(VIEW_KEY) || "draw");
  const [nav, setNav] = React.useState("esteiras");
  const [railOpen, setRailOpen] = React.useState(false);
  const RAIL_W = 76, RAIL_W_OPEN = 236;
  const [company, setCompany] = React.useState(() => localStorage.getItem(COMPANY_KEY) || "nnstudio");
  const [coOpen, setCoOpen] = React.useState(false);
  React.useEffect(() => { localStorage.setItem(COMPANY_KEY, company); }, [company]);
  const co = COMPANIES[company] || COMPANIES.nnstudio;
  const [env, setEnv] = React.useState("teste");
  const [envOpen, setEnvOpen] = React.useState(false);
  const [showNewAgent, setShowNewAgent] = React.useState(false);
  const [credMcp, setCredMcp] = React.useState(null);
  const [view, setView] = React.useState({ x: 60, y: 40, k: 0.8 });
  const runningRef = React.useRef(false);
  React.useEffect(() => { localStorage.setItem(VIEW_KEY, mode); }, [mode]);

  const dark = tweaks.theme === "dark";
  const t = React.useMemo(() => themeFor(dark), [dark]);
  // Viveo is a fresh, empty workspace — no agents, pipes or MCPs yet.
  const liveAgents = company === "viveo" ? EMPTY_AGENTS : agents;
  const brand = BRANDS[company] || BRANDS.nnstudio;
  const railBg = dark ? t.railBg : brand.rail;
  // per-tenant accent ramp — overrides the NN.ai tokens on this subtree.
  // Dark = paleta NN do standalone (periwinkle), igual em qualquer tenant.
  const accentVars = dark ? {
    "--brand-teal-700": "#9bbcd9", "--brand-teal-600": "#aecbe0",
    "--brand-teal-500": "#aecbe0", "--brand-teal-400": "#c7dbea",
    "--brand-teal-accent": "rgba(174,203,224,.18)",
  } : {
    "--brand-teal-700": brand.accent700, "--brand-teal-600": brand.accent600,
    "--brand-teal-500": brand.accent500, "--brand-teal-400": brand.accent400,
    "--brand-teal-accent": brand.navActive,
  };
  const canvasRef = React.useRef(null);
  const areaRef = React.useRef(null);

  // edges (estáticas + conexões criadas pelo usuário)
  const [userEdges, setUserEdges] = React.useState([]);
  const edges = React.useMemo(() => [...EDGES, ...userEdges].map((e) => ({ ...e, label: tweaks.edgeLabels ? e.label : "" })), [tweaks.edgeLabels, userEdges]);
  const onConnect = React.useCallback((from, to) => {
    setUserEdges((arr) => {
      if (!from || !to || from === to) return arr;
      if ([...EDGES, ...arr].some((e) => (e.from === from && e.to === to) || (e.from === to && e.to === from))) return arr;
      return [...arr, { from, to, label: "" }];
    });
  }, [EDGES]);

  // ---- persistence ----
  React.useEffect(() => {
    const map = {}; agents.forEach((a) => (map[a.id] = a.pos));
    localStorage.setItem(POS_KEY, JSON.stringify(map));
  }, [agents]);
  React.useEffect(() => { localStorage.setItem(TWK_KEY, JSON.stringify(tweaks)); }, [tweaks]);

  // ---- tweaks host protocol ----
  React.useEffect(() => {
    const onMsg = (e) => {
      const d = e.data || {};
      if (d.type === "__activate_edit_mode") setShowTweaks(true);
      if (d.type === "__deactivate_edit_mode") setShowTweaks(false);
    };
    window.addEventListener("message", onMsg);
    window.parent?.postMessage({ type: "__edit_mode_available" }, "*");
    return () => window.removeEventListener("message", onMsg);
  }, []);
  const setTweak = (k, v) => {
    setTweaks((tw) => ({ ...tw, [k]: v }));
    window.parent?.postMessage({ type: "__edit_mode_set_keys", edits: { [k]: v } }, "*");
  };

  // ---- handlers ----
  const onMovePos = React.useCallback((id, pos) => {
    setAgents((arr) => arr.map((a) => (a.id === id ? { ...a, pos } : a)));
  }, []);
  const onUpdate = React.useCallback((id, patch) => {
    setAgents((arr) => arr.map((a) => (a.id === id ? { ...a, ...patch } : a)));
  }, []);
  const onResult = React.useCallback((id) => {
    setAgents((arr) => arr.map((a) => {
      if (a.id !== id) return a;
      const st = a.status === "error" ? "warn" : "ok";
      const tk = 800 + Math.floor(Math.random() * 60000);
      const titles = {
        nf: "Execução manual · lote NF-e", concilia: "Execução manual · conciliação",
        triagem: "Execução manual · triagem de vaga", contratos: "Execução manual · minuta gerada",
        atendimento: "Execução manual · atendimento",
      };
      const sums = {
        nf: "Documentos processados e validados em tempo real", concilia: "Lançamentos conciliados com extrato",
        triagem: "Currículos pontuados e ranqueados", contratos: "Minuta gerada e enviada para revisão",
        atendimento: st === "warn" ? "Processado com fila parcial (WhatsApp offline)" : "Mensagens respondidas e registradas",
      };
      const r = { time: "agora", title: titles[a.id], status: st, summary: sums[a.id], tokens: tk, dur: a.metrics.p95 };
      return { ...a, recent: [r, ...a.recent].slice(0, 6) };
    }));
  }, []);

  const sources = React.useMemo(() => {
    const incoming = new Set(EDGES.map((e) => e.to));
    return AGENTS.filter((a) => !incoming.has(a.id)).map((a) => a.id);
  }, []);
  const childrenMap = React.useMemo(() => {
    const c = {};
    EDGES.forEach((e) => { (c[e.from] = c[e.from] || []).push(e.to); });
    return c;
  }, []);

  const runCascade = React.useCallback(async (starts) => {
    if (runningRef.current || !starts || !starts.length) return;
    runningRef.current = true; setRunning(true); setNodeRun({});
    let layer = [...new Set(starts)];
    const seen = new Set();
    let guard = 0;
    while (layer.length && guard++ < 12) {
      layer.forEach((id) => seen.add(id));
      setNodeRun((s) => { const n = { ...s }; layer.forEach((id) => (n[id] = "processing")); return n; });
      await sleepApp(900);
      setNodeRun((s) => { const n = { ...s }; layer.forEach((id) => (n[id] = "done")); return n; });
      layer.forEach((id) => onResult(id));
      const nextEdges = [];
      layer.forEach((id) => (childrenMap[id] || []).forEach((to) => nextEdges.push([id, to])));
      if (nextEdges.length) await (canvasRef.current?.animateEdges(nextEdges) || sleepApp(700));
      layer = [...new Set(nextEdges.map((e) => e[1]))].filter((id) => !seen.has(id));
    }
    await sleepApp(650);
    setNodeRun({});
    runningRef.current = false; setRunning(false);
  }, [childrenMap, onResult]);

  const runAll = () => runCascade(sources);
  const runFrom = (ids) => runCascade(ids);

  // ---- fit view ----
  const fitView = React.useCallback(() => {
    const el = areaRef.current; if (!el || !liveAgents.length) return false;
    const W = el.clientWidth, H = el.clientHeight, pad = 70;
    if (!W || !H) return false; // área ainda não medida (race no mount) — tenta de novo
    const xs = liveAgents.map((a) => a.pos.x), ys = liveAgents.map((a) => a.pos.y);
    const minX = Math.min(...xs) - pad, minY = Math.min(...ys) - pad;
    const maxX = Math.max(...liveAgents.map((a) => a.pos.x + NODE_W_APP)) + pad;
    const maxY = Math.max(...liveAgents.map((a) => a.pos.y + NODE_H_APP)) + pad;
    const k = Math.max(0.1, Math.min(W / (maxX - minX), H / (maxY - minY), 1.05));
    setView({ k, x: (W - (maxX - minX) * k) / 2 - minX * k, y: (H - (maxY - minY) * k) / 2 - minY * k });
    return true;
  }, [liveAgents]);
  React.useEffect(() => {
    let tries = 0, id;
    const tick = () => { if (fitView() || tries++ > 40) return; id = setTimeout(tick, 80); };
    id = setTimeout(tick, 60);
    return () => clearTimeout(id);
  }, [fitView]);

  // ---- criar agente a partir do modal ----
  const handleCreateAgent = (template) => {
    let newId = null;
    setAgents((arr) => {
      const maxX = arr.length ? Math.max(...arr.map((a) => a.pos.x)) : -220;
      const topY = arr.length ? Math.min(...arr.map((a) => a.pos.y)) : 150;
      newId = "new-" + Date.now();
      const novo = {
        id: newId,
        name: template.name,
        short: "Novo agente",
        role: template.desc,
        status: "ok",
        llm: "gpt-4o",
        pos: { x: maxX + 360, y: topY },
        accent: "#8fb3d4",
        mcps: [],
        metrics: { tokensDay: 0, tokensMonth: 0, calls: 0, cost: 0, costMonth: 0, p95: "—", success: 100, saved: "—" },
        spark: Array.from({ length: 24 }, (_, i) => 28 + Math.round(Math.sin(i / 2.2) * 6)),
        prompt: "",
        versions: [],
        recent: [],
        runs: [],
      };
      return [...arr, novo];
    });
    setShowNewAgent(false);
    setNav("esteiras");
    setMode("draw");
  };

  const selected = liveAgents.find((a) => a.id === selectedId);

  // ---- KPI totals ----
  const totals = React.useMemo(() => ({
    ativos: liveAgents.filter((a) => a.status === "ok").length,
    atencao: liveAgents.filter((a) => a.status === "warn").length,
    falha: liveAgents.filter((a) => a.status === "error").length,
    tokens: liveAgents.reduce((s, a) => s + a.metrics.tokensDay, 0),
    custo: liveAgents.reduce((s, a) => s + a.metrics.cost, 0),
    calls: liveAgents.reduce((s, a) => s + a.metrics.calls, 0),
  }), [liveAgents]);

  const ENVIRONMENTS = window.AgentData.ENVIRONMENTS;
  const envFg = env === "prod" ? "#15803d" : "#ff6a5f";
  const envBg = env === "prod" ? (dark ? "rgba(21,128,61,.22)" : "#ecfdf3") : (dark ? "rgba(217,45,32,.18)" : "#FEE4E2");
  const envLabel = env === "prod" ? "Produção" : "Base Teste";

  const pendingAppr = company === "viveo" ? 0 : window.AgentData.APPROVALS.length;
  const openCrit = company === "viveo" ? 0 : window.AgentData.ALERTS.filter((a) => a.sev === "critical" && a.status === "open").length;
  const navItems = [
    { id: "esteiras", i: "git-branch", label: "Esteiras" },
    { id: "execucoes", i: "history", label: "Execuções" },
    { id: "aprovacoes", i: "check", label: "Aprovações", badge: pendingAppr },
    { id: "alertas", i: "bell", label: "Alertas", dot: openCrit > 0 },
    { id: "modelos", i: "cpu", label: "Modelos" },
    { id: "mcps", i: "plug", label: "MCPs" },
    { id: "roi", i: "trending-up", label: "ROI" },
  ];

  return (
    <div className={`app${dark ? " dark" : ""}${tweaks.mcpMotion ? "" : " no-motion"}`} style={{ ...accentVars, position: "relative", display: "flex", height: "100vh", overflow: "hidden", background: t.pageBg, color: t.ink, fontFamily: "var(--font-sans)" }}>
      {/* RAIL spacer — reserva 60px no layout (o rail flutua por cima) */}
      <div style={{ width: RAIL_W, flex: `0 0 ${RAIL_W}px` }} />
      {/* RAIL — expande no hover por cima do conteúdo, mostrando os nomes dos menus */}
      <aside onMouseEnter={() => setRailOpen(true)} onMouseLeave={() => setRailOpen(false)}
        style={{ position: "absolute", left: 0, top: 0, bottom: 0, width: railOpen ? RAIL_W_OPEN : RAIL_W, transition: "width .22s cubic-bezier(.22,1,.36,1)", background: railBg, display: "flex", flexDirection: "column", padding: "22px 0 18px", gap: 6, zIndex: 50, borderRight: dark ? "1px solid #18181b" : "none", overflow: "hidden", boxShadow: railOpen ? "8px 0 34px rgba(0,0,0,.5)" : "none" }}>
        <div style={{ display: "flex", alignItems: "center", justifyContent: railOpen ? "flex-start" : "center", padding: railOpen ? "0 17px" : 0, marginBottom: 28, flex: "none" }}>
          <div title="Plataforma de Agentes · nn.ai" style={{ width: 42, height: 42, flex: "none", border: dark ? "1px solid rgba(174,203,224,.22)" : `1px solid ${t.chipBorder}`, borderRadius: 12, overflow: "hidden", boxShadow: dark ? "0 0 22px rgba(58,143,220,.22)" : "none" }}>
            <img src="assets/nn-avatar.png" alt="nn.ai" style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} />
          </div>
        </div>
        {navItems.map((r) => {
          const on = nav === r.id;
          return (
            <button key={r.id} title={railOpen ? undefined : r.label} onClick={() => setNav(r.id)} className="rail-btn"
              style={{ position: "relative", width: railOpen ? "auto" : 46, height: 46, margin: railOpen ? "0 12px" : "0 auto", borderRadius: 13, display: "flex", alignItems: "center", justifyContent: railOpen ? "flex-start" : "center", gap: railOpen ? 13 : 0, padding: railOpen ? "0 12px" : 0, overflow: railOpen ? "hidden" : "visible",
                background: on ? (dark ? "rgba(174,203,224,.08)" : brand.navActive) : "transparent",
                border: `1px solid ${on && dark ? "rgba(174,203,224,.2)" : "transparent"}`,
                color: on ? (dark ? "#cfe0ec" : "#fff") : (dark ? "#6f6f74" : "rgba(255,255,255,.6)"),
                boxShadow: on && dark ? "0 0 18px rgba(58,143,220,.18)" : "none" }}>
              <Icon name={r.i} size={22} stroke={1.7} style={{ flex: "none" }} />
              {railOpen && <span style={{ fontSize: 13.5, fontWeight: 600, whiteSpace: "nowrap" }}>{r.label}</span>}
              {r.badge ? <span style={{ ...(railOpen ? { marginLeft: "auto" } : { position: "absolute", top: 7, right: 8 }), minWidth: 16, height: 16, padding: "0 4px", borderRadius: 9, background: "#e07a82", color: "#150708", fontSize: 9.5, fontWeight: 700, display: "grid", placeItems: "center", boxShadow: railOpen ? "none" : "0 0 10px rgba(224,122,130,.55)", flex: "none" }}>{r.badge}</span> : null}
              {r.dot && !r.badge && <span style={{ ...(railOpen ? { marginLeft: "auto" } : { position: "absolute", top: 9, right: 11 }), width: 7, height: 7, borderRadius: "50%", background: "#72b2e6", boxShadow: "0 0 8px #72b2e6", flex: "none" }} />}
              {on && !railOpen && <span style={{ position: "absolute", left: -13, top: 13, width: 3, height: 20, background: dark ? "#aecbe0" : "#fff", borderRadius: 3, boxShadow: dark ? "0 0 10px #72b2e6" : "none" }} />}
            </button>
          );
        })}
        <div style={{ flex: 1 }} />
        <button onClick={() => setNav("config")} className="rail-btn" title={railOpen ? undefined : "Configurações"}
          style={{ position: "relative", width: railOpen ? "auto" : 46, height: 46, margin: railOpen ? "0 12px" : "0 auto", borderRadius: 13, display: "flex", alignItems: "center", justifyContent: railOpen ? "flex-start" : "center", gap: railOpen ? 13 : 0, padding: railOpen ? "0 12px" : 0, overflow: railOpen ? "hidden" : "visible",
            background: nav === "config" ? (dark ? "rgba(174,203,224,.08)" : brand.navActive) : "transparent",
            border: `1px solid ${nav === "config" && dark ? "rgba(174,203,224,.2)" : "transparent"}`,
            color: nav === "config" ? (dark ? "#cfe0ec" : "#fff") : (dark ? "#6f6f74" : "rgba(255,255,255,.6)"),
            boxShadow: nav === "config" && dark ? "0 0 18px rgba(58,143,220,.18)" : "none" }}>
          <Icon name="sliders-horizontal" size={22} stroke={1.7} style={{ flex: "none" }} />
          {railOpen && <span style={{ fontSize: 13.5, fontWeight: 600, whiteSpace: "nowrap" }}>Configurações</span>}
          {nav === "config" && !railOpen && <span style={{ position: "absolute", left: -13, top: 13, width: 3, height: 20, background: dark ? "#aecbe0" : "#fff", borderRadius: 3, boxShadow: dark ? "0 0 10px #72b2e6" : "none" }} />}
        </button>
        <div style={{ display: "flex", alignItems: "center", gap: 11, padding: railOpen ? "0 18px" : 0, justifyContent: railOpen ? "flex-start" : "center", marginTop: 18, flex: "none" }}>
          <span style={{ width: 38, height: 38, flex: "none", borderRadius: 999, background: dark ? "linear-gradient(150deg,#1d2b36,#0c1318)" : brand.avatar, border: dark ? "1px solid rgba(174,203,224,.28)" : "none", display: "grid", placeItems: "center", color: dark ? "#cfe0ec" : "#fff", fontWeight: 700, fontSize: 12, letterSpacing: ".04em" }}>NS</span>
          {railOpen && <span style={{ fontSize: 12.5, fontWeight: 600, color: t.ink2, whiteSpace: "nowrap" }}>nn studio</span>}
        </div>
        <div title="Plataforma por nn.ai" style={{ marginTop: 16, display: "flex", flexDirection: railOpen ? "row" : "column", alignItems: "center", justifyContent: "center", gap: railOpen ? 7 : 4, padding: railOpen ? "0 18px" : 0, flex: "none" }}>
          <span style={{ fontSize: 7.5, letterSpacing: ".22em", textTransform: "uppercase", color: "#4a4a4e" }}>by</span>
          <NNMark height={11} onDark />
        </div>
      </aside>

      {/* MAIN */}
      <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column" }}>
        {/* HEADER — só na tela de esteiras (os outros módulos têm cabeçalho próprio) */}
        {nav === "esteiras" && (
        <header className="esteiras-header" style={{ height: 92, flex: "0 0 92px", background: dark ? "linear-gradient(180deg,#0a0a0c,#070708)" : "#fff", borderBottom: `1px solid ${dark ? "#18181b" : t.panelBorder}`, display: "flex", alignItems: "center", padding: "0 18px", gap: 18, zIndex: 20 }}>
          {/* esquerda: título + ambiente */}
          <div style={{ minWidth: 240, flexShrink: 0 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
              <span className="hdr-title" style={{ fontFamily: "var(--font-brand)", fontSize: 23, fontWeight: 700, letterSpacing: "-.02em", color: t.ink, whiteSpace: "nowrap" }}>Central de Agentes</span>
              <div className="r-hide-phone" style={{ position: "relative" }}>
                <button onClick={() => setEnvOpen((o) => !o)} style={{ display: "inline-flex", alignItems: "center", gap: 7, height: 26, padding: "0 11px", borderRadius: 200, background: dark ? "rgba(174,203,224,.1)" : envBg, border: dark ? "1px solid rgba(174,203,224,.32)" : 0, color: dark ? "#cfe0ec" : envFg, fontSize: 10.5, fontWeight: 700, letterSpacing: ".13em", textTransform: "uppercase", cursor: "pointer", fontFamily: "inherit" }}>
                  {envLabel} <Icon name="chevron-down" size={11} stroke={2.4} />
                </button>
                {envOpen && (
                  <div style={{ position: "absolute", top: "calc(100% + 7px)", left: 0, width: 252, background: dark ? "#0a0a0c" : "#fff", border: `1px solid ${t.panelBorder}`, borderRadius: 12, boxShadow: "0 18px 44px rgba(13,56,59,.25)", zIndex: 70, overflow: "hidden", padding: 6 }}>
                    {ENVIRONMENTS.map((e) => (
                      <button key={e.id} onClick={() => { setEnv(e.id); setEnvOpen(false); }} style={{ width: "100%", display: "flex", alignItems: "center", gap: 10, padding: "9px 10px", borderRadius: 9, border: 0, cursor: "pointer", background: env === e.id ? t.statBg : "transparent", textAlign: "left", fontFamily: "inherit" }}>
                        <span style={{ width: 9, height: 9, borderRadius: 9, background: e.color, flex: "0 0 9px" }} />
                        <div style={{ flex: 1, minWidth: 0 }}>
                          <div style={{ fontSize: 12.5, fontWeight: 700, color: t.ink }}>{e.label}</div>
                          <div style={{ fontSize: 10, color: t.ink3 }}>{e.note}</div>
                        </div>
                        {env === e.id && <Icon name="check" size={15} stroke={2.4} style={{ color: "var(--brand-teal-600)" }} />}
                      </button>
                    ))}
                    <div style={{ borderTop: `1px solid ${t.cardBorder}`, margin: "5px 0", paddingTop: 6 }}>
                      <button onClick={() => { setEnv("prod"); setEnvOpen(false); }} style={{ width: "100%", display: "flex", alignItems: "center", justifyContent: "center", gap: 7, padding: "9px 10px", borderRadius: 9, border: 0, cursor: "pointer", background: "var(--brand-teal-600)", color: "#06121c", fontSize: 11.5, fontWeight: 700, fontFamily: "inherit" }}>
                        <Icon name="arrow-right" size={13} /> Promover para Produção
                      </button>
                    </div>
                  </div>
                )}
              </div>
            </div>
            <p className="hdr-sub" style={{ margin: "5px 0 0", fontSize: 11.5, letterSpacing: ".16em", textTransform: "uppercase", color: dark ? "rgba(207,207,207,.42)" : t.ink3, whiteSpace: "nowrap" }}>{co.tagline}</p>
          </div>

          {/* centro: métricas */}
          {company !== "viveo" ? (
          <div className="r-topstats" style={{ flex: 1, minWidth: 0, display: "flex", alignItems: "center", justifyContent: "center", gap: 34 }}>
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 6 }}>
              <div style={{ display: "flex", alignItems: "center", gap: 13 }}>
                {[["ok", totals.ativos], ["warn", totals.atencao], ["error", totals.falha]].map(([k, n]) => (
                  <span key={k} style={{ display: "flex", alignItems: "center", gap: 5, fontSize: 17, fontWeight: 700, color: t.ink }}><span style={{ width: 8, height: 8, borderRadius: "50%", background: STATUS[k].orb, boxShadow: `0 0 9px ${STATUS[k].orb}` }} />{n}</span>
                ))}
              </div>
              <span style={{ fontSize: 9.5, letterSpacing: ".18em", color: dark ? "rgba(207,207,207,.42)" : t.ink3 }}>SAÚDE</span>
            </div>
            {[["TOKENS HOJE", fmtTokens(totals.tokens)], ["CUSTO HOJE", fmtBRL(totals.custo)], ["ACIONAMENTOS", fmtNum(totals.calls)]].map(([l, v]) => (
              <React.Fragment key={l}>
                <span style={{ width: 1, height: 34, background: dark ? "#222226" : t.chipBorder }} />
                <div style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 6 }}>
                  <span style={{ fontSize: 18, fontWeight: 700, color: t.ink, letterSpacing: "-.01em" }}>{v}</span>
                  <span style={{ fontSize: 9.5, letterSpacing: ".18em", color: dark ? "rgba(207,207,207,.42)" : t.ink3 }}>{l}</span>
                </div>
              </React.Fragment>
            ))}
          </div>
          ) : <div style={{ flex: 1 }} />}

          {/* direita: controles */}
          <div style={{ display: "flex", alignItems: "center", gap: 12, flexShrink: 0 }}>
            {company !== "viveo" && (
            <div className="view-toggle r-hide-phone" style={{ display: "flex", padding: 4, gap: 3, borderRadius: 12, background: dark ? "#0e0e10" : t.statBg, border: `1px solid ${dark ? "#1f1f22" : t.chipBorder}` }}>
              {[
                ["draw", "Tela livre", <svg key="d" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round"><circle cx="6" cy="6" r="2" /><circle cx="6" cy="18" r="2" /><circle cx="18" cy="12" r="2" /><path d="M6 8v8M8 6.5c5 .5 4 4.5 8 5.5M8 17.5c5-.5 4-4.5 8-5.5" /></svg>],
                ["grid", "Pipelines", <svg key="g" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"><path d="M3 6l9-3 9 3-9 3-9-3ZM3 12l9 3 9-3M3 18l9 3 9-3" /></svg>],
              ].map(([m, l, ic]) => {
                const on = mode === m;
                return (
                  <button key={m} onClick={() => setMode(m)} title={l}
                    style={{ display: "inline-flex", alignItems: "center", gap: 7, height: 34, padding: "0 13px", borderRadius: 9, cursor: "pointer", fontFamily: "inherit", fontSize: 12.5, fontWeight: 600, whiteSpace: "nowrap", border: `1px solid ${on ? (dark ? "rgba(174,203,224,.26)" : t.chipBorder) : "transparent"}`, background: on ? (dark ? "rgba(174,203,224,.12)" : "#fff") : "transparent", color: on ? (dark ? "#cfe0ec" : t.ink) : t.ink3 }}>
                    {ic} {l}
                  </button>
                );
              })}
            </div>
            )}
            {company !== "viveo" && (
            <button onClick={runAll} disabled={running} className="r-hide-phone" style={{ display: "flex", alignItems: "center", gap: 9, height: 42, padding: "0 19px", borderRadius: 12, background: running ? t.ink3 : "#aecbe0", border: "none", color: "#06121c", fontSize: 13.5, fontWeight: 700, letterSpacing: ".01em", cursor: running ? "default" : "pointer", boxShadow: running ? "none" : "0 0 20px rgba(174,203,224,.34)", fontFamily: "inherit", opacity: running ? .7 : 1 }}>
              {running ? <Icon name="loader" size={15} className="spin" /> : <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 4.5v15l13-7.5z" /></svg>}
              {running ? "Executando esteiras…" : "Executar todas"}
            </button>
            )}
            <button onClick={() => setShowNewAgent(true)} style={{ display: "flex", alignItems: "center", gap: 8, height: 42, padding: "0 17px", borderRadius: 12, background: company === "viveo" ? "#0F4B55" : (dark ? "#101012" : t.statBg), border: company === "viveo" ? "none" : `1px solid ${dark ? "#262629" : t.chipBorder}`, color: company === "viveo" ? "#fff" : (dark ? "#e2e1df" : t.ink), fontSize: 13.5, fontWeight: 600, cursor: "pointer", fontFamily: "inherit" }}>
              <Icon name="plus" size={15} stroke={2} /> <span className="r-novolabel">Novo agente</span>
            </button>
          </div>
        </header>
        )}

        {/* CANVAS AREA */}
        <div ref={areaRef} style={{ flex: 1, position: "relative", overflow: "hidden" }}>
          {company === "viveo" && <ViveoEmptyState nav={nav} t={t} dark={dark} onNew={() => setShowNewAgent(true)} />}

          {company !== "viveo" && (<>
          {nav !== "esteiras" && (
            nav === "execucoes" ? <RunsModule agents={agents} t={t} dark={dark} onSelect={setSelectedId} /> :
            nav === "aprovacoes" ? <ApprovalsModule agents={agents} t={t} dark={dark} onSelect={setSelectedId} /> :
            nav === "alertas" ? <AlertsModule agents={agents} t={t} dark={dark} onSelect={setSelectedId} /> :
            nav === "modelos" ? <ModelsModule agents={agents} t={t} dark={dark} onSelect={setSelectedId} /> :
            nav === "mcps" ? <McpsModule agents={agents} t={t} dark={dark} onSelect={setSelectedId} onEditCreds={setCredMcp} /> :
            nav === "roi" ? <RoiModule agents={agents} t={t} dark={dark} onSelect={setSelectedId} /> :
            nav === "config" ? <SettingsModule t={t} dark={dark} /> : null
          )}

          {nav === "esteiras" && (mode === "draw" ? (
            <AgentCanvas ref={canvasRef} agents={agents} edges={edges} t={t} dark={dark} grid={tweaks.grid}
              selectedId={selectedId} nodeRun={nodeRun} onSelect={setSelectedId} onMovePos={onMovePos}
              onConnect={onConnect} view={view} setView={setView} />
          ) : (
            <PipelineView agents={agents} edges={edges} t={t} dark={dark} nodeRun={nodeRun}
              selectedId={selectedId} onSelect={setSelectedId} running={running} onRun={runFrom} />
          ))}

          {/* legend (canvas only) */}
          {nav === "esteiras" && mode === "draw" && (
          <div style={{ position: "absolute", left: 26, bottom: 24, display: "flex", gap: 18, alignItems: "center", height: 42, padding: "0 19px", background: dark ? "rgba(14,16,19,.78)" : "rgba(255,255,255,.86)", backdropFilter: "blur(10px)", WebkitBackdropFilter: "blur(10px)", border: `1px solid ${dark ? "#1f1f22" : t.chipBorder}`, borderRadius: 200, fontSize: 12, color: dark ? "#cfcfcf" : t.ink2, boxShadow: t.cardShadow }}>
            {[["ok", "Operacional"], ["warn", "Atenção"], ["error", "Falha"]].map(([k, l]) => (
              <span key={k} style={{ display: "inline-flex", alignItems: "center", gap: 8 }}><span style={{ width: 9, height: 9, borderRadius: "50%", background: STATUS[k].orb, boxShadow: `0 0 8px ${STATUS[k].orb}` }} />{l}</span>
            ))}
          </div>
          )}

          {/* zoom controls (canvas only) */}
          {nav === "esteiras" && mode === "draw" && (
          <div style={{ position: "absolute", right: selected ? 460 : 26, bottom: 24, display: "flex", flexDirection: "column", alignItems: "center", gap: 10, transition: "right .28s cubic-bezier(.22,1,.36,1)" }}>
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", background: dark ? "rgba(14,16,19,.82)" : "#fff", backdropFilter: "blur(10px)", WebkitBackdropFilter: "blur(10px)", border: `1px solid ${dark ? "#1f1f22" : t.chipBorder}`, borderRadius: 14, overflow: "hidden", boxShadow: t.cardShadow }}>
              <button className="zoom-btn" onClick={() => setView((v) => ({ ...v, k: Math.min(2.2, v.k * 1.18) }))} style={{ color: dark ? "#cfcfcf" : t.ink }}><Icon name="plus" size={17} stroke={2} /></button>
              <div style={{ fontSize: 11, fontWeight: 600, textAlign: "center", color: "#aecbe0", padding: "5px 0" }}>{Math.round(view.k * 100)}%</div>
              <button className="zoom-btn" onClick={() => setView((v) => ({ ...v, k: Math.max(0.35, v.k * 0.85) }))} style={{ color: dark ? "#cfcfcf" : t.ink }}><Icon name="minus" size={17} stroke={2} /></button>
            </div>
            <button className="zoom-btn solo" onClick={fitView} title="Recentralizar" style={{ background: dark ? "rgba(14,16,19,.82)" : "#fff", backdropFilter: "blur(10px)", WebkitBackdropFilter: "blur(10px)", border: `1px solid ${dark ? "#1f1f22" : t.chipBorder}`, color: "#aecbe0", boxShadow: t.cardShadow }}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><circle cx="12" cy="12" r="4" /><path d="M12 2v3M12 19v3M2 12h3M19 12h3" /></svg>
            </button>
          </div>
          )}

          {/* hint */}
          {!selected && nav === "esteiras" && mode === "draw" && (
            <div style={{ position: "absolute", left: "50%", top: 22, transform: "translateX(-50%)", display: "flex", gap: 10, alignItems: "center", height: 42, padding: "0 19px", background: dark ? "rgba(14,16,19,.72)" : "rgba(255,255,255,.84)", backdropFilter: "blur(10px)", WebkitBackdropFilter: "blur(10px)", border: `1px solid ${dark ? "rgba(174,203,224,.16)" : t.chipBorder}`, borderRadius: 200, fontSize: 12.5, color: dark ? "rgba(226,225,223,.8)" : t.ink2, boxShadow: "0 18px 48px rgba(0,0,0,.4)", whiteSpace: "nowrap" }}>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#aecbe0" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l1.6 4.6L18 9l-4.4 1.4L12 15l-1.6-4.6L6 9l4.4-1.4L12 3Z" /><path d="M19 14l.8 2.2L22 17l-2.2.8L19 20l-.8-2.2L16 17l2.2-.8L19 14Z" /></svg>
              Arraste para navegar · scroll para zoom · clique num agente para abrir
            </div>
          )}
          </>)}
        </div>
      </div>

      {/* PANEL */}
      {selected && <DetailPanel agent={selected} t={t} dark={dark} onClose={() => setSelectedId(null)} onUpdate={onUpdate} onRun={runFrom} running={running} onEditCreds={setCredMcp} />}

      {/* NEW AGENT */}
      {showNewAgent && <NewAgentModal t={t} dark={dark} onClose={() => setShowNewAgent(false)} onCreate={handleCreateAgent} />}

      {/* MCP CREDENTIALS */}
      {credMcp && <McpCredentialsModal mcp={credMcp} t={t} dark={dark} onClose={() => setCredMcp(null)} />}

      {/* TWEAKS */}
      {showTweaks && (
        <div className="tweaks" style={{ background: dark ? "#0a0a0c" : "#fff", border: `1px solid ${t.panelBorder}`, color: t.ink }}>
          <div style={{ fontWeight: 700, fontSize: 13, marginBottom: 12, display: "flex", alignItems: "center", gap: 7 }}><Icon name="sliders-horizontal" size={15} /> Tweaks</div>

          <div className="twk-row">
            <span style={{ color: t.ink2 }}>Tema do canvas</span>
            <div className="seg">
              {[["claro", "Claro"], ["dark", "Control room"]].map(([v, l]) => (
                <button key={v} onClick={() => setTweak("theme", v)} className={tweaks.theme === v ? "on" : ""}>{l}</button>
              ))}
            </div>
          </div>
          <label className="twk-toggle"><span style={{ color: t.ink2 }}>Rótulos das conexões</span><input type="checkbox" checked={tweaks.edgeLabels} onChange={(e) => setTweak("edgeLabels", e.target.checked)} /></label>
          <label className="twk-toggle"><span style={{ color: t.ink2 }}>Figurinhas dos MCPs animadas</span><input type="checkbox" checked={tweaks.mcpMotion} onChange={(e) => setTweak("mcpMotion", e.target.checked)} /></label>
          <label className="twk-toggle"><span style={{ color: t.ink2 }}>Grade de fundo</span><input type="checkbox" checked={tweaks.grid} onChange={(e) => setTweak("grid", e.target.checked)} /></label>

          <div style={{ fontSize: 10.5, color: t.ink3, marginTop: 12, lineHeight: 1.5, borderTop: `1px solid ${t.chipBorder}`, paddingTop: 10 }}>
            Dica: clique em <b>Executar todas</b> para ver os dados fluírem pela esteira nó a nó.
          </div>
        </div>
      )}
    </div>
  );
}

window.AgentApp = App;
