// App root, sidebar, role switch, real page routing.
const { useState, useEffect } = React;
const { OverviewPage, FleetPage, ConnectionsPage, GovernancePage, RecommendationsPage, CostsPage, ComingSoonPage, TemplatePage } = window;
const { OperatorView, OperatorCostsPage, OperatorTestsPage, AppDetailDrawer, OwnerChip, CmdKPalette } = window;
const { ServiceDetailModal, ContractProposalModal, AddRuleModal, TemplatingKitModal, GrantExceptionModal, OutboundDecisionModal, BudgetIncreaseModal, RuleInspectModal, ShipNewAppModal, NewTestModal } = window;
const { SettingsPage } = window;
const { Icons, DATA, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor } = window;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#FF6600",
  "density": "comfortable",
  "startRole": "cto"
}/*EDITMODE-END*/;

const CTO_NAV = [
  { id: "overview",    label: "Overview",        icon: "Home" },
  { id: "recommendations", label: "Recommendations", icon: "Spark", badge: 5 },
  { id: "fleet",       label: "Fleet",           icon: "Fleet",    badge: 24 },
  { id: "governance",  label: "Rules",           icon: "Shield" },
  { id: "template",    label: "Template",        icon: "Box",     badge: 3 },
  { id: "connections", label: "Connections",     icon: "Graph",
    children: [
      { id: "connections-third", label: "Third Party", count: 17 },
      { id: "connections-data",  label: "Data",        count: 8  },
    ]},
  { id: "costs",       label: "Cost attribution",icon: "Dollar" },
];

const OPERATOR_NAV = [
  { id: "overview",   label: "My work",     icon: "Home" },
  { id: "fleet",      label: "My apps",     icon: "Fleet",  badge: 3 },
  { id: "connections",label: "Dependencies",icon: "Graph",
    children: [
      { id: "connections-third", label: "Third Party", count: 17 },
      { id: "connections-data",  label: "Data",        count: 8  },
    ]},
  { id: "tests",      label: "Tests",       icon: "Flask" },
  { id: "costs",      label: "My costs",    icon: "Dollar" },
];

function Sidebar({ active, setActive, role }) {
  const nav = role === "cto" ? CTO_NAV : OPERATOR_NAV;
  return (
    <aside className="sidebar">
      <div className="brand">
        <span className="dot"/>
        Stoda
        <small>control plane</small>
      </div>
      <div className="nav-group">
        <h5>{role === "cto" ? "Governance" : "Workspace"}</h5>
        {nav.map(n => {
          const Ic = Icons[n.icon];
          // A parent is "active" when any of its children is selected, or its own id is selected.
          const isActive = active === n.id || (n.children && n.children.some(c => c.id === active));
          // For parent nav items, default click goes to first child.
          const onTopClick = () => {
            if (n.children && n.children.length) setActive(n.children[0].id);
            else setActive(n.id);
          };
          return (
            <React.Fragment key={n.id}>
              <button className={"nav-item" + (isActive ? " active" : "")} onClick={onTopClick}>
                <Ic/> <span>{n.label}</span>
                {n.badge && <span className="badge">{n.badge}</span>}
              </button>
              {n.children && isActive && (
                <div style={{ marginLeft: 28, display: "flex", flexDirection: "column", gap: 2, marginTop: 2, marginBottom: 4 }}>
                  {n.children.map(c => (
                    <button key={c.id}
                      className={"nav-item sub" + (active === c.id ? " active" : "")}
                      onClick={() => setActive(c.id)}>
                      <span style={{ flex: 1 }}>{c.label}</span>
                      {c.count != null && <span style={{ fontSize: 11, color: "var(--muted-2)", fontVariantNumeric: "tabular-nums" }}>{c.count}</span>}
                    </button>
                  ))}
                </div>
              )}
            </React.Fragment>
          );
        })}
      </div>
      <div className="nav-group">
        <h5>Reference</h5>
        <button className="nav-item" onClick={() => setActive("settings")}><Icons.Gear/> Settings</button>
      </div>

      <div style={{ marginTop: 24, padding: 12, border: "1px solid var(--tan-2)", borderRadius: 10, background: "var(--cream-3)" }}>
        <div className="eyebrow" style={{ fontSize: 10 }}>BYOC cloud</div>
        <div style={{ fontSize: 13, color: "var(--ink)", fontWeight: 500, marginTop: 4 }}>AWS · us-east-1</div>
        <div style={{ fontSize: 11.5, color: "var(--muted)", marginTop: 2 }}>account 8421 · 24 apps deployed</div>
        <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 8 }}>
          <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--green)" }}/>
          <span style={{ fontSize: 11.5, color: "var(--green)" }}>Control plane healthy</span>
        </div>
      </div>
    </aside>
  );
}

function Topbar({ role, setRole, onOpenCmdK }) {
  const user = role === "cto" ? DATA.ME_CTO : DATA.ME_OPERATOR;
  return (
    <div className="topbar">
      <div style={{ display: "flex", gap: 12, alignItems: "center", flex: 1, maxWidth: 480 }}>
        <button onClick={onOpenCmdK}
          style={{ display: "flex", alignItems: "center", gap: 8,
            background: "var(--paper)", border: "1px solid var(--tan-2)",
            borderRadius: 8, padding: "7px 12px", width: "100%",
            cursor: "pointer", textAlign: "left", fontFamily: "inherit" }}>
          <Icons.Search/>
          <span style={{ flex: 1, fontSize: 13, color: "var(--muted-2)" }}>Search apps, schemas, rules…</span>
          <span className="shortcut">⌘K</span>
        </button>
      </div>

      <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
        <div className="role-switch" title="Same data, different permissions">
          <button className={role === "cto" ? "on" : ""} onClick={() => setRole("cto")}>
            <span className="avatar" style={{ background: "linear-gradient(135deg,#E8D9C7,#FFB98A)" }}>PR</span>
            CTO view
          </button>
          <button className={role === "operator" ? "on" : ""} onClick={() => setRole("operator")}>
            <span className="avatar" style={{ background: DATA.OPERATORS.ml.color }}>ML</span>
            Operator view
          </button>
        </div>
        {role === "operator" && (
          <button className="btn icon ghost" title="Notifications" style={{ position: "relative" }}>
            <Icons.Bell/>
            <span style={{ position: "absolute", top: 3, right: 3, width: 7, height: 7, borderRadius: "50%", background: "var(--orange)" }}/>
          </button>
        )}
        <div className="user-chip">
          <span className="avatar">{user.initials}</span>
          <div>
            <div style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)", lineHeight: 1.2 }}>{user.name}</div>
            <div style={{ fontSize: 11, color: "var(--muted)", lineHeight: 1.1 }}>{role === "cto" ? "CTO · Meridia" : user.team}</div>
          </div>
        </div>
      </div>
    </div>
  );
}

function Toast({ text, sub, onClose }) {
  useEffect(() => {
    const t = setTimeout(onClose, 4200);
    return () => clearTimeout(t);
  }, []);
  return (
    <div className="toast-wrap">
      <div className="toast">
        <Icons.Arrow s={14}/>
        <span>{text}</span>
        {sub && <span className="pill">{sub}</span>}
      </div>
    </div>
  );
}

// Coming-soon content per page
const COMING = {
  costs: {
    title: <>Cost <em>attributed</em> to the people using it.</>,
    eyebrow: "Cost attribution · Per-app P&L",
    description: "Compute, external APIs, and LLM spend, attributed to the team owner, not a shared key.",
    icon: "Dollar",
    items: ["Per-team P&L", "Shared-key splitter", "Budget alerts", "Forecasts", "Export to finance"],
  },
  tests: {
    title: <>Operator <em>tests.</em></>,
    eyebrow: "Tests · Recorded once, replayed always",
    description: "Workflow tests authored by operators, the contract Stoda enforces on every deploy.",
    icon: "Flask",
    items: ["My tests", "Team tests", "Recordings", "Golden paths", "Coverage map"],
  },

  signals: {
    title: <>Every <em>signal.</em></>,
    eyebrow: "Signals · Opportunities + attention",
    description: "The full ranked list of things worth your time, from wins to drifts.",
    icon: "Spark",
    items: ["All signals", "Opportunities", "Attention", "Dismissed", "Routed to others"],
  },
};

function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [role, setRole] = useState(tweaks.startRole || "cto");
  const [active, setActive] = useState("overview");
  const [openApp, setOpenApp] = useState(null);
  const [openService, setOpenService] = useState(null);
  // Per-service policy overrides. Values: 'allowed' | 'blocked' | undefined (inherit posture).
  const [tpPosture, setTpPosture] = useState("default-deny"); // default-deny | default-allow
  const [policyOverrides, setPolicyOverrides] = useState({
    "Twilio · SMS":            "blocked",
    "Anthropic · Sonnet":      "allowed",
    "OpenAI · GPT-4o":         "allowed",
    "Anthropic · Haiku":       "allowed",
    "Salesforce REST":         "allowed",
    "Stripe":                  "allowed",
    "DocuSign":                "allowed",
    "NetSuite":                "allowed",
    "BambooHR":                "allowed",
    "Slack":                   "allowed",
    "Mailgun":                 "allowed",
    "Segment":                 "allowed",
    "Hubspot":                 "allowed",
    "Ironclad":                "allowed",
    "SAP Ariba":               "allowed",
    "Typeform":                "allowed",
  });
  const policyFor = (name) => policyOverrides[name] || "inherit";
  const setPolicy = (name, v) => setPolicyOverrides(p => {
    const next = { ...p };
    if (v === "inherit") delete next[name];
    else next[name] = v;
    return next;
  });
  const [showContract, setShowContract] = useState(false);
  const [showAddRule, setShowAddRule] = useState(false);
  const [showTemplating, setShowTemplating] = useState(false);
  const [showException, setShowException] = useState(false);
  const [showOutbound, setShowOutbound] = useState(false);
  const [showInspect, setShowInspect] = useState(false);
  const [inspectRule, setInspectRule] = useState(null);
  const [outboundMode, setOutboundMode] = useState("allow"); // "allow" | "block"
  const [showBudget, setShowBudget] = useState(false);
  const [showShipNew, setShowShipNew] = useState(false);
  const [showNewTest, setShowNewTest] = useState(false);
  const [newTestApp, setNewTestApp] = useState(null);
  const [rulePreset, setRulePreset] = useState(null);
  const [toast, setToast] = useState(null);
  const [cmdkOpen, setCmdkOpen] = useState(false);

  // Global ⌘K / Ctrl+K hotkey
  useEffect(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        setCmdkOpen(o => !o);
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  // Cmd-K nav handler, supports special role-switch tokens
  const handleCmdKNav = (target) => {
    if (typeof target === "string" && target.startsWith("__role:")) {
      const r = target.split(":")[1];
      setRole(r);
      setActive("overview");
      setToast({ text: `Switched to ${r === "cto" ? "CTO" : "Operator"} view`, sub: "role" });
      return;
    }
    setActive(target);
  };

  useEffect(() => {
    document.documentElement.style.setProperty("--orange", tweaks.accent);
    document.body.dataset.density = tweaks.density;
    document.body.style.setProperty("font-size", tweaks.density === "compact" ? "13px" : "14px");
  }, [tweaks]);

  const handleOpenSignal = (s) => {
    switch (s.action) {
      case "exception": setShowException(true); return;
      case "outbound":  setShowOutbound(true); return;
      case "budget":    setShowBudget(true); return;
      case "rule-keys": setRulePreset("lib-7"); setShowAddRule(true); return;
      case "contract":  setShowContract(true); return;
      default: setToast({ text: s.title, sub: "decision" });
    }
  };

  const handleOpenRec = handleOpenSignal;

  const handleRequestApproval = () => {
    setToast({ text: "Approval routed to Priya", sub: "handoff" });
  };

  const renderPage = () => {
    if (role === "operator") {
      if (active === "overview") return <OperatorView onOpenApp={setOpenApp} onRequestApproval={handleRequestApproval} onNav={setActive} onShipNew={() => setShowShipNew(true)} onNewTest={(app) => { setNewTestApp(app || null); setShowNewTest(true); }}/>;
      if (active === "fleet")    return <FleetPage onOpenApp={setOpenApp} role="operator"/>;
      if (active === "settings") return <SettingsPage role={role}/>;
      if (active === "costs")    return <OperatorCostsPage onOpenApp={setOpenApp} onOpenBudget={() => setShowBudget(true)}/>;
      if (active === "tests")    return <OperatorTestsPage onOpenApp={setOpenApp} onNewTest={() => setShowNewTest(true)}/>;
      if (active === "connections" || active === "connections-third" || active === "connections-data") return <ConnectionsPage onOpenApp={setOpenApp} onOpenService={setOpenService} onOpenContract={() => setShowContract(true)} initialTab={active === "connections-data" ? "data" : "third-party"} tpPosture={tpPosture} setTpPosture={setTpPosture} policyFor={policyFor} setPolicy={setPolicy}/>;
      // everything else → coming soon
      const cfg = COMING[active] || COMING.signals;
      return <ComingSoonPage {...cfg}/>;
    }
    // CTO
    switch (active) {
      case "overview":        return <OverviewPage onOpenApp={setOpenApp} onOpenSignal={handleOpenSignal} onOpenRec={handleOpenRec} onNav={setActive} onOpenContract={() => setShowContract(true)}/>;
      case "template":        return <TemplatePage onOpenApp={setOpenApp}/>;
      case "fleet":           return <FleetPage onOpenApp={setOpenApp}/>;
      case "connections":
      case "connections-third":
      case "connections-data":
        return <ConnectionsPage onOpenApp={setOpenApp} onOpenService={setOpenService} onOpenContract={() => setShowContract(true)} initialTab={active === "connections-data" ? "data" : "third-party"} tpPosture={tpPosture} setTpPosture={setTpPosture} policyFor={policyFor} setPolicy={setPolicy}/>;
      case "governance":      return <GovernancePage onAddRule={() => setShowAddRule(true)} onInspect={(id) => { setInspectRule(id); setShowInspect(true); }}/>;
      case "recommendations": return <RecommendationsPage onOpenApp={setOpenApp} onOpenRec={handleOpenRec}/>;
      case "costs":           return <CostsPage onOpenApp={setOpenApp} onOpenService={setOpenService} onOpenBudget={() => setShowBudget(true)}/>;
      case "settings":        return <SettingsPage role={role}/>;
      default: {
        const cfg = COMING[active] || COMING.signals;
        return <ComingSoonPage {...cfg}/>;
      }
    }
  };

  return (
    <div className="app">
      <Sidebar active={active} setActive={setActive} role={role}/>
      <div className="main">
        <Topbar role={role} setRole={(r) => { setRole(r); setActive("overview"); }} onOpenCmdK={() => setCmdkOpen(true)}/>
        <div className="page">{renderPage()}</div>
      </div>

      {openApp && <AppDetailDrawer app={openApp} role={role} onClose={() => setOpenApp(null)} onOpenOutbound={(mode = "allow") => { setOutboundMode(mode); setShowOutbound(true); }} onOpenException={() => setShowException(true)} onOpenBudget={() => setShowBudget(true)}/>}
      {openService && <ServiceDetailModal service={openService} onClose={() => setOpenService(null)} onOpenApp={(name) => {
        const a = DATA.APPS.find(x => x.name === name);
        if (a) { setOpenService(null); setOpenApp(a); }
      }} policy={policyFor(openService.name)} onSetPolicy={(v) => setPolicy(openService.name, v)} posture={tpPosture}/>}
      <ContractProposalModal open={showContract} onClose={() => setShowContract(false)}/>
      <AddRuleModal open={showAddRule} onClose={() => { setShowAddRule(false); setRulePreset(null); }} presetRuleId={rulePreset}/>
      <TemplatingKitModal open={showTemplating} onClose={() => setShowTemplating(false)}/>
      <GrantExceptionModal open={showException} onClose={() => setShowException(false)}/>
      <OutboundDecisionModal open={showOutbound} mode={outboundMode} onClose={() => setShowOutbound(false)}/>
      <BudgetIncreaseModal open={showBudget} onClose={() => setShowBudget(false)}/>
      <ShipNewAppModal open={showShipNew} onClose={() => setShowShipNew(false)}/>
      <NewTestModal open={showNewTest} app={newTestApp} onClose={() => { setShowNewTest(false); setNewTestApp(null); }}/>
      <RuleInspectModal open={showInspect} ruleId={inspectRule} onClose={() => setShowInspect(false)}/>
      {toast && <Toast {...toast} onClose={() => setToast(null)}/>}

      <CmdKPalette
        open={cmdkOpen}
        onClose={() => setCmdkOpen(false)}
        onNav={handleCmdKNav}
        onOpenApp={(a) => { setOpenApp(a); }}
        role={role}
      />

      <TweaksPanel title="Tweaks">
        <TweakSection title="Appearance">
          <TweakColor label="Accent" value={tweaks.accent} onChange={(v) => setTweak("accent", v)}/>
          <TweakRadio label="Density" value={tweaks.density}
            options={[{ value: "comfortable", label: "Comfortable" }, { value: "compact", label: "Compact" }]}
            onChange={(v) => setTweak("density", v)}/>
        </TweakSection>
        <TweakSection title="Start">
          <TweakRadio label="Open in" value={tweaks.startRole}
            options={[{ value: "cto", label: "CTO view" }, { value: "operator", label: "Operator view" }]}
            onChange={(v) => setTweak("startRole", v)}/>
        </TweakSection>
      </TweaksPanel>
    </div>
  );
}

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