/* Voyage Fleet — app shell.
 * Hash router, collapsible grouped sidebar, topbar (breadcrumbs + search + AI toggle),
 * and the AppShell layout that docks the AI rail on the right.
 * Exports: useRoute, navigate, setParam, Sidebar, Topbar, AppShell.
 */

const { useState: useState_s, useEffect: useEffect_s, useRef: useRef_s } = React;

/* ─── Hash router with query params ────────────────────────────────────── */
function parseHash() {
  let h = window.location.hash || "#/";
  if (!h.startsWith("#")) h = "#/" + h;
  h = h.slice(1) || "/";
  const [pathRaw, query] = h.split("?");
  const path = pathRaw || "/";
  const params = Object.fromEntries(new URLSearchParams(query || ""));
  return { path, params };
}
function useRoute() {
  const [route, setRoute] = useState_s(parseHash());
  useEffect_s(() => {
    const fn = () => setRoute(parseHash());
    window.addEventListener("hashchange", fn);
    return () => window.removeEventListener("hashchange", fn);
  }, []);
  return route;
}
function navigate(path, params) {
  let target = path.startsWith("/") ? path : "/" + path;
  if (params && Object.keys(params).length) {
    const clean = {};
    Object.entries(params).forEach(([k, v]) => { if (v != null && v !== "" && v !== false) clean[k] = v; });
    const qs = new URLSearchParams(clean).toString();
    if (qs) target += "?" + qs;
  }
  window.location.hash = "#" + target;
}
/* Merge/replace params on the current route (preserves URL state). */
function setParam(updates) {
  const { path, params } = parseHash();
  navigate(path, { ...params, ...updates });
}
Object.assign(window, { useRoute, navigate, setParam });

/* ─── Sidebar ──────────────────────────────────────────────────────────── */
const NAV_GROUPS = [
  { label: "Fleet", items: [
    { id: "overview",  path: "/",          label: "Fleet Overview", icon: <Icons.Gauge /> },
    { id: "drift",     path: "/drift",     label: "Drift Report",   icon: <Icons.Drift /> },
  ]},
  { label: "Tenants", items: [
    { id: "tenants",   path: "/tenants",   label: "All Tenants",    icon: <Icons.Fleet /> },
    { id: "new",       path: "/new",       label: "New Tenant",     icon: <Icons.Plus />, accent: true },
  ]},
  { label: "Catalog", items: [
    { id: "modules",   path: "/modules",   label: "Components",     icon: <Icons.Module /> },
  ]},
  { label: "Operations", items: [
    { id: "audit",     path: "/audit",     label: "Audit Log",      icon: <Icons.Audit /> },
  ]},
  { label: "Settings", items: [
    { id: "settings",  path: "/settings",  label: "Settings",       icon: <Icons.Settings /> },
  ]},
];

function Sidebar({ active, collapsed, onToggle }) {
  const W = collapsed ? 60 : 224;
  return (
    <aside aria-label="Fleet navigation" style={{
      width: W, flexShrink: 0, background: "white", borderRight: "1px solid var(--jrni-color-surface-border)",
      display: "flex", flexDirection: "column", transition: "width 160ms var(--jrni-motion-easing-standard)", overflow: "hidden",
    }}>
      {/* brand */}
      <div style={{ height: 56, display: "flex", alignItems: "center", gap: 10, padding: collapsed ? "0 14px" : "0 16px", borderBottom: "1px solid var(--jrni-color-surface-border)", flexShrink: 0 }}>
        <span style={{ width: 30, height: 30, borderRadius: 7, background: "var(--jrni-color-primary-1)", color: "white", display: "grid", placeItems: "center", flexShrink: 0 }}>
          <Icons.Fleet size={17} color="white" />
        </span>
        {!collapsed ? (
          <div style={{ lineHeight: 1.15, minWidth: 0 }}>
            <div style={{ fontSize: 14, fontWeight: 700, color: "var(--jrni-color-neutral-1)" }}>Voyage Fleet</div>
            <div style={{ fontSize: 10.5, color: "var(--jrni-color-text-soft)", letterSpacing: 0.02 }}>Control plane</div>
          </div>
        ) : null}
      </div>

      {/* nav */}
      <nav style={{ flex: 1, overflowY: "auto", padding: "10px 8px" }}>
        {NAV_GROUPS.map(g => (
          <div key={g.label} style={{ marginBottom: 14 }}>
            {!collapsed ? (
              <div style={{ fontSize: 10, fontWeight: 700, color: "var(--jrni-color-neutral-3)", textTransform: "uppercase", letterSpacing: 0.06, padding: "0 10px 6px" }}>{g.label}</div>
            ) : <div style={{ height: 1, background: "var(--jrni-color-surface-border)", margin: "0 8px 10px" }} />}
            <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 2 }}>
              {g.items.map(it => {
                const isActive = active === it.id;
                return (
                  <li key={it.id}>
                    <button onClick={() => navigate(it.path)} title={collapsed ? it.label : undefined} style={{
                      width: "100%", display: "flex", alignItems: "center", gap: 10,
                      padding: collapsed ? "0" : "0 10px", height: 34, justifyContent: collapsed ? "center" : "flex-start",
                      borderRadius: 6, border: "none", cursor: "pointer", position: "relative",
                      background: isActive ? "var(--jrni-color-primary-3)" : "transparent",
                      color: isActive ? "var(--jrni-color-primary-1)" : it.accent ? "var(--jrni-color-primary-1)" : "var(--jrni-color-neutral-2)",
                      fontSize: 13.5, fontWeight: isActive ? 600 : 500, fontFamily: "var(--jrni-font-family-sans)", textAlign: "left",
                    }}>
                      <span style={{ display: "inline-flex", flexShrink: 0 }}>{it.icon}</span>
                      {!collapsed ? <span style={{ flex: 1, whiteSpace: "nowrap" }}>{it.label}</span> : null}
                      {isActive && !collapsed ? <span style={{ position: "absolute", left: 0, top: 7, width: 3, height: 20, background: "var(--jrni-color-primary-1)", borderRadius: 999 }} /> : null}
                    </button>
                  </li>
                );
              })}
            </ul>
          </div>
        ))}
      </nav>

      {/* collapse toggle */}
      <button onClick={onToggle} style={{
        height: 40, borderTop: "1px solid var(--jrni-color-surface-border)", border: "none", borderTopStyle: "solid",
        borderTopWidth: 1, borderTopColor: "var(--jrni-color-surface-border)", background: "white", cursor: "pointer",
        display: "flex", alignItems: "center", justifyContent: collapsed ? "center" : "flex-start", gap: 8,
        padding: collapsed ? 0 : "0 16px", color: "var(--jrni-color-text-soft)", fontSize: 12.5, fontWeight: 500, fontFamily: "var(--jrni-font-family-sans)",
      }}>
        <Icons.Chevron dir={collapsed ? "right" : "left"} size={14} />
        {!collapsed ? "Collapse" : null}
      </button>
    </aside>
  );
}

/* ─── Breadcrumbs ──────────────────────────────────────────────────────── */
function Breadcrumbs({ trail }) {
  return (
    <nav aria-label="Breadcrumb" style={{ display: "flex", alignItems: "center", gap: 7, minWidth: 0 }}>
      {trail.map((c, i) => (
        <span key={i} style={{ display: "inline-flex", alignItems: "center", gap: 7, minWidth: 0 }}>
          {i > 0 ? <Icons.Chevron dir="right" size={11} color="var(--jrni-color-neutral-3)" /> : null}
          {c.path && i < trail.length - 1 ? (
            <button onClick={() => navigate(c.path)} style={{ background: "none", border: "none", cursor: "pointer", padding: 0, fontSize: 13, fontWeight: 500, color: "var(--jrni-color-text-soft)", fontFamily: "var(--jrni-font-family-sans)", whiteSpace: "nowrap" }}>{c.label}</button>
          ) : (
            <span style={{ fontSize: 13, fontWeight: 600, color: "var(--jrni-color-neutral-1)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: 260 }}>{c.label}</span>
          )}
        </span>
      ))}
    </nav>
  );
}

/* ─── Topbar ───────────────────────────────────────────────────────────── */
function Topbar({ trail, onOpenSearch, role, onSetRole }) {
  const [profileOpen, setProfileOpen] = useState_s(false);
  const ref = useRef_s(null);
  useOutsideClick(ref, () => setProfileOpen(false));
  const roleMeta = { cs: "Customer Success", pe: "Platform Engineer", rm: "Voyage Release Manager" };
  const roleLabel = roleMeta[role] || "Platform Engineer";
  return (
    <header style={{
      height: 56, flexShrink: 0, background: "white", borderBottom: "1px solid var(--jrni-color-surface-border)",
      display: "flex", alignItems: "center", gap: 16, padding: "0 16px 0 20px",
    }}>
      <Breadcrumbs trail={trail} />
      <div style={{ flex: 1 }} />
      <button onClick={onOpenSearch} style={{
        display: "flex", alignItems: "center", gap: 8, height: 34, padding: "0 10px", width: 280,
        border: "1px solid var(--jrni-color-neutral-4)", borderRadius: 6, background: "white", cursor: "pointer",
        color: "var(--jrni-color-text-soft)", boxShadow: "var(--jrni-shadow-chrome)",
      }}>
        <Icons.Search size={14} color="var(--jrni-color-neutral-3)" />
        <span style={{ flex: 1, textAlign: "left", fontSize: 13 }}>Search tenants, components…</span>
        <span style={{ fontSize: 11, color: "var(--jrni-color-text-soft)", border: "1px solid var(--jrni-color-surface-border)", borderRadius: 4, padding: "1px 6px", fontFamily: "var(--jrni-font-family-mono)" }}>⌘K</span>
      </button>

      <button title="Alerts" style={{ width: 34, height: 34, borderRadius: 6, border: "1px solid var(--jrni-color-neutral-4)", background: "white", cursor: "pointer", display: "grid", placeItems: "center", position: "relative", boxShadow: "var(--jrni-shadow-chrome)" }}>
        <Icons.Bell size={16} color="var(--jrni-color-neutral-1)" />
        <span style={{ position: "absolute", top: -3, right: -3, minWidth: 15, height: 15, padding: "0 3px", background: "var(--jrni-color-semantic-red-1)", color: "white", borderRadius: 999, fontSize: 9, fontWeight: 700, display: "grid", placeItems: "center", border: "1.5px solid white" }}>6</span>
      </button>
      <div ref={ref} style={{ position: "relative" }}>
        <button onClick={() => setProfileOpen(o => !o)} style={{
          display: "flex", alignItems: "center", gap: 8, height: 34, padding: "0 8px 0 4px",
          background: "white", border: "1px solid var(--jrni-color-neutral-4)", borderRadius: 999, cursor: "pointer", boxShadow: "var(--jrni-shadow-chrome)",
        }}>
          <Avatar initials="LO" color="var(--jrni-color-tertiary-light-blue)" size={26} />
          <span style={{ textAlign: "left", lineHeight: 1.1 }}>
            <span style={{ display: "block", fontSize: 12.5, fontWeight: 600, color: "var(--jrni-color-neutral-1)" }}>Lori Owens</span>
            <span style={{ display: "block", fontSize: 10, color: "var(--jrni-color-text-soft)" }}>{roleLabel}</span>
          </span>
          <Icons.Chevron size={12} />
        </button>
        {profileOpen ? (
          <div style={{ position: "absolute", top: "calc(100% + 6px)", right: 0, width: 246, background: "white", borderRadius: 8, boxShadow: "var(--jrni-shadow-lg)", border: "1px solid var(--jrni-color-surface-border)", padding: 4, zIndex: 120 }}>
            <div style={{ padding: "10px 12px", borderBottom: "1px solid var(--jrni-color-surface-border)", marginBottom: 4 }}>
              <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--jrni-color-neutral-1)" }}>Lori Owens</div>
              <div style={{ fontSize: 12, color: "var(--jrni-color-text-soft)" }}>lori@voyage.dev</div>
              <div style={{ marginTop: 6 }}><Pill tone="primary">{roleLabel}</Pill></div>
            </div>
            <div style={{ padding: "6px 12px 4px", fontSize: 10, fontWeight: 700, color: "var(--jrni-color-neutral-3)", textTransform: "uppercase", letterSpacing: 0.05 }}>View as role <span style={{ fontWeight: 500, textTransform: "none", letterSpacing: 0 }}>· demo</span></div>
            {[["cs", "Customer Success"], ["pe", "Platform Engineer"], ["rm", "Release Manager"]].map(r => (
              <MenuItem key={r[0]} icon={role === r[0] ? <Icons.Check size={14} /> : <span style={{ width: 14 }} />} onClick={() => { onSetRole && onSetRole(r[0]); setProfileOpen(false); }}>{r[1]}</MenuItem>
            ))}
            <div style={{ height: 1, background: "var(--jrni-color-surface-border)", margin: "4px 0" }} />
            <MenuItem icon={<Icons.Settings size={14} />} onClick={() => { setProfileOpen(false); navigate("/settings"); }}>Settings</MenuItem>
            <MenuItem icon={<Icons.Logout size={14} />}>Sign out</MenuItem>
          </div>
        ) : null}
      </div>
    </header>
  );
}

/* ─── AppShell ─────────────────────────────────────────────────────────── */
function AppShell({ active, trail, children, onOpenSearch, role, onSetRole }) {
  const [collapsed, setCollapsed] = useState_s(false);
  return (
    <div style={{ height: "100dvh", display: "flex", background: "var(--jrni-color-surface-canvas)", overflow: "hidden" }}>
      <Sidebar active={active} collapsed={collapsed} onToggle={() => setCollapsed(c => !c)} />
      <div style={{ flex: 1, minWidth: 0, display: "flex", flexDirection: "column", minHeight: 0 }}>
        <Topbar trail={trail} onOpenSearch={onOpenSearch} role={role} onSetRole={onSetRole} />
        <div style={{ flex: 1, minHeight: 0, display: "flex", overflow: "hidden" }}>
          <main style={{ flex: 1, minWidth: 0, overflowY: "auto", display: "flex", flexDirection: "column" }}>{children}</main>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { Sidebar, Topbar, AppShell, Breadcrumbs });
