// SQSEO app left sidebar: workspace switcher, command-palette launcher, page nav
// with live count badges, settings, and a plan-aware upgrade card. Reads
// window.LTQ.boot; switching uses window.LTQ.api + reloadBoot (no page reload).
(function init(){
if(!window.LongtailIQDesignSystem_ae8f12 || !window.LTQ || !window.LTQ.Popover || !window.LTQ.t){return setTimeout(init,30);}
const React = window.React;
const DS = window.LongtailIQDesignSystem_ae8f12;
const { Icon } = DS;
const { Popover, MenuItem, api, reloadBoot, toast, t } = window.LTQ;

// `countKey` ties a nav item to a field in boot.counts so the badge stays live.
const NAV = [
  { id: "dashboard", label: "Overview", icon: "layout-grid" },
  { id: "performance", label: "Performance", icon: "line-chart", countKey: "pages" },
  { id: "insights", label: "Insights", icon: "activity" },
  { id: "ai-visibility", label: "AI Visibility", icon: "radar" },
  { id: "research", label: "Keyword Research", icon: "search", countKey: "keywords" },
  { id: "lab", label: "Research Lab", icon: "flask-conical" },
  { id: "ai", label: "AI Search Queries", icon: "sparkles", countKey: "aiQueries" },
  { id: "competitor", label: "Competitor Gaps", icon: "git-compare" },
  { id: "links", label: "Link Opportunities", icon: "link" },
  { id: "audit", label: "Site Audit", icon: "clipboard-check" },
  { id: "content", label: "Content Ideas", icon: "lightbulb" },
  { id: "calendar", label: "Content Plan", icon: "calendar-days" },
  { id: "saved", label: "Saved Lists", icon: "bookmark", countKey: "savedLists" },
  { id: "exports", label: "Reports", icon: "file-bar-chart" },
];
window.LTQ.NAV = NAV; // shared with the command palette

const planLabelOf = (plan) =>
  ["free", "pro", "team"].includes(plan) ? t("plan." + plan)
    : plan ? t("plan.other", { name: plan.charAt(0).toUpperCase() + plan.slice(1) }) : t("plan.free");
const fmtCount = (n) => (n >= 1000 ? (n / 1000).toFixed(n >= 10000 ? 0 : 1) + "k" : String(n));
const DIVIDER = <div style={{ height: 1, background: "var(--border-subtle)", margin: "5px 4px" }} />;

function NavItem({ item, active, onClick, count }) {
  const [hover, setHover] = React.useState(false);
  return (
    <button onClick={onClick} onMouseEnter={()=>setHover(true)} onMouseLeave={()=>setHover(false)}
      style={{ position: "relative", zIndex: 1, display: "flex", alignItems: "center", gap: 10, width: "100%", height: 34, padding: "0 10px",
        border: "none", borderRadius: 8, cursor: "pointer", textAlign: "left",
        fontFamily: "var(--font-sans)", fontSize: 13.5, fontWeight: active ? 600 : 500, letterSpacing: "-0.01em",
        // The active highlight is drawn by the shared spring indicator behind the
        // items (see Sidebar), so the active item itself stays transparent.
        background: active ? "transparent" : hover ? "var(--ink-50)" : "transparent",
        color: active ? "var(--text-strong)" : "var(--text-muted)",
        transition: "color var(--dur-fast) var(--ease-out)" }}>
      <Icon name={item.icon} size={16} strokeWidth={active ? 2 : 1.8} style={{ color: active ? "var(--text-strong)" : "var(--text-faint)" }} />
      <span style={{ flex: 1, minWidth: 0 }}>{t("nav." + item.id)}</span>
      {count != null && count > 0 && (
        <span style={{ flex: "none", fontFamily: "var(--font-mono)", fontSize: 10.5, fontWeight: 600,
          color: active ? "var(--text-strong)" : "var(--text-faint)",
          background: active ? "var(--paper)" : "var(--ink-50)", border: "1px solid var(--border-subtle)",
          borderRadius: 6, padding: "1px 6px", lineHeight: 1.5 }}>{fmtCount(count)}</span>
      )}
    </button>
  );
}

function WorkspaceSwitcher({ onNavigate }) {
  const boot = window.LTQ.boot || {};
  const ws = boot.workspace || {};
  const workspaces = boot.workspaces || [];
  const switchWs = async (w, close) => {
    close();
    if (w.id === boot.active_workspace) return;
    const r = await api.post("/api/workspace/switch", { workspaceId: w.id });
    if (r.ok) { await reloadBoot(); toast(t("chrome.switched_to", { name: w.name })); }
    else toast(r.error || t("chrome.switch_failed"), { tone: "error" });
  };
  return (
    <Popover align="left" width={252}
      trigger={(open, toggle) => (
        <button onClick={toggle} style={{ display: "flex", alignItems: "center", gap: 9, flex: 1, minWidth: 0, height: "100%", border: "none", background: "transparent", cursor: "pointer", padding: 0 }}>
          <span style={{ display: "flex", flexDirection: "column", alignItems: "flex-start", lineHeight: 1.2, flex: 1, minWidth: 0 }}>
            <span style={{ fontSize: 13.5, fontWeight: 600, color: "var(--text-strong)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "100%" }}>{ws.name || t("chrome.my_workspace")}</span>
            <span style={{ fontSize: 11, color: "var(--text-faint)" }}>{planLabelOf(ws.plan)}</span>
          </span>
          <Icon name="chevrons-up-down" size={15} style={{ color: "var(--text-faint)", flex: "none" }} />
        </button>
      )}>
      {(close) => (
        <>
          <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-faint)", letterSpacing: "0.02em", padding: "4px 9px 6px" }}>{t("chrome.workspaces")}</div>
          {workspaces.map((w) => (
            <MenuItem key={w.id} icon="layers" label={w.name} sub={planLabelOf(w.plan)}
              active={w.id === boot.active_workspace}
              trailing={w.id === boot.active_workspace ? <Icon name="check" size={15} style={{ color: "var(--accent-500)", flex: "none" }} /> : null}
              onClick={() => switchWs(w, close)} />
          ))}
          {DIVIDER}
          <MenuItem icon="settings-2" label={t("chrome.workspace_settings")} onClick={() => { close(); onNavigate && onNavigate("settings"); }} />
        </>
      )}
    </Popover>
  );
}

function Sidebar({ active, onNavigate, open, onOpenPalette, onClose }) {
  const boot = window.LTQ.boot || {};
  const counts = boot.counts || {};
  const plan = (boot.workspace && boot.workspace.plan) || "free";
  const isPaid = plan === "pro" || plan === "team";

  // ---- spring-driven active indicator (MV-4) ----
  // One highlight pill glides between nav items on a real damped spring. Because
  // the spring keeps position AND velocity, rapid navigation retargets mid-glide
  // and flows continuously — a CSS transition would restart from the old spot on
  // every click. Reduced-motion snaps instantly (the engine handles that).
  const navRef = React.useRef(null);
  const indRef = React.useRef(null);
  const springRef = React.useRef(null);
  const mountedRef = React.useRef(false);
  const wasHiddenRef = React.useRef(false);
  const activeIndex = NAV.findIndex((n) => n.id === active);
  React.useLayoutEffect(() => {
    const nav = navRef.current, ind = indRef.current;
    if (!nav || !ind) return;
    if (activeIndex < 0) { ind.style.opacity = "0"; wasHiddenRef.current = true; return; }
    const el = nav.querySelectorAll("button")[activeIndex];
    if (!el) return;
    const top = el.offsetTop;
    ind.style.opacity = "1";
    ind.style.height = el.offsetHeight + "px";
    const S = window.LTQSpring;
    if (!S) { ind.style.transform = "translateY(" + top + "px)"; return; }
    if (!springRef.current) {
      springRef.current = S.createSpring(Object.assign(S.fromResponse(0.38, 0.9), {
        from: top, restDelta: 0.1, restSpeed: 0.5,
        onUpdate: (v) => { if (indRef.current) indRef.current.style.transform = "translateY(" + v + "px)"; },
      }));
    }
    // First paint (or re-appearing after a non-nav page) snaps into place; a
    // normal nav→nav change glides and can be interrupted.
    if (!mountedRef.current || wasHiddenRef.current) {
      mountedRef.current = true; wasHiddenRef.current = false;
      springRef.current.jump(top);
    } else {
      springRef.current.set(top);
    }
  }, [active, activeIndex]);

  // ---- mobile drawer: swipe-to-close with a real velocity throw (MV-4) ----
  // Drag the open drawer leftward; on release the gesture's velocity + offset
  // decide open vs closed and the spring throws it there with inertia (a flick
  // closes even from a small drag). touch-action:pan-y lets vertical scroll pass
  // through, so no passive-listener preventDefault fight. Desktop/no-touch never
  // triggers it (guarded by `open`, and touch events simply don't fire).
  const asideRef = React.useRef(null);
  const dragRef = React.useRef(null);
  const onTouchStart = (e) => {
    if (!open || !e.touches || e.touches.length !== 1) return;
    const t = e.touches[0];
    dragRef.current = { x0: t.clientX, y0: t.clientY, t0: performance.now(),
      dx: 0, moved: false, axis: false, w: (asideRef.current && asideRef.current.offsetWidth) || 280 };
  };
  const onTouchMove = (e) => {
    const d = dragRef.current; if (!d) return;
    const t = e.touches[0];
    const dx = t.clientX - d.x0, dy = t.clientY - d.y0;
    if (!d.moved) {
      if (Math.abs(dx) < 6 && Math.abs(dy) < 6) return;
      if (Math.abs(dy) > Math.abs(dx)) { dragRef.current = null; return; } // vertical → let it scroll
      d.moved = true;
      if (asideRef.current) asideRef.current.style.transition = "none";
    }
    const clamped = Math.max(-d.w, Math.min(0, dx)); // leftward only
    d.dx = clamped; d.vx = t.clientX; d.vt = performance.now();
    if (asideRef.current) asideRef.current.style.transform = "translateX(" + clamped + "px)";
    const bd = document.querySelector(".lt-backdrop");
    if (bd) bd.style.opacity = String(Math.max(0, 1 - Math.abs(clamped) / d.w));
  };
  const settleDrawer = (el, bd, close) => {
    if (el) { el.style.transition = ""; el.style.transform = ""; }
    if (bd) bd.style.opacity = "";
    if (close && onClose) onClose();
  };
  const onTouchEnd = () => {
    const d = dragRef.current; dragRef.current = null;
    if (!d || !d.moved) return;
    const el = asideRef.current, bd = document.querySelector(".lt-backdrop");
    const velPxPerS = ((d.vx - d.x0) / Math.max(1, d.vt - d.t0)) * 1000; // negative = left
    const shouldClose = d.dx < -d.w * 0.4 || velPxPerS < -450;
    const S = window.LTQSpring;
    if (!S || S.reducedMotion()) { settleDrawer(el, bd, shouldClose); return; }
    const sp = S.createSpring({ from: d.dx, velocity: velPxPerS, stiffness: 320, damping: 36, restDelta: 0.3, restSpeed: 2,
      onUpdate: (v) => {
        if (el) el.style.transform = "translateX(" + v + "px)";
        if (bd) bd.style.opacity = String(Math.max(0, 1 - Math.abs(v) / d.w));
      },
      onRest: () => settleDrawer(el, bd, shouldClose),
    });
    sp.set(shouldClose ? -d.w : 0);
  };

  return (
    <aside ref={asideRef} className={"lt-sidebar" + (open ? " open" : "")}
      onTouchStart={onTouchStart} onTouchMove={onTouchMove} onTouchEnd={onTouchEnd} onTouchCancel={onTouchEnd}
      style={{ width: "var(--sidebar-w)", flex: "none", height: "100%", background: "var(--paper)", touchAction: "pan-y",
      borderRight: "1px solid var(--border-subtle)", display: "flex", flexDirection: "column", padding: "12px 12px" }}>

      {/* Workspace switcher; logo links back to the marketing site */}
      <div style={{ display: "flex", alignItems: "center", gap: 9, width: "100%", height: 46, padding: "0 8px",
        border: "1px solid transparent", borderRadius: 10 }}>
        <a href="/" title={t("chrome.back_to_site")} style={{ display: "flex", flex: "none" }}>
          <img src="../assets/logo-mark.svg" width="28" height="28" alt="SQSEO" style={{ borderRadius: 8 }} />
        </a>
        <WorkspaceSwitcher onNavigate={onNavigate} />
      </div>

      {/* Command palette launcher */}
      <button onClick={onOpenPalette} style={{ display: "flex", alignItems: "center", gap: 8, height: 34, padding: "0 10px", margin: "10px 0 14px",
        border: "1px solid var(--border-subtle)", borderRadius: 8, background: "var(--ink-50)", cursor: "pointer", width: "100%" }}>
        <Icon name="search" size={14} style={{ color: "var(--text-faint)" }} />
        <span style={{ flex: 1, fontSize: 12.5, color: "var(--text-faint)", textAlign: "left" }}>{t("chrome.quick_actions")}</span>
        <kbd style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, color: "var(--text-faint)", background: "var(--paper)", border: "1px solid var(--border-subtle)", borderRadius: 5, padding: "1px 5px" }}>⌘K</kbd>
      </button>

      {/* The guided setup is a standalone first-run screen now (onboarding
          revamp Phase 12) — the shell never renders while it's needed, so the
          old "Finish setup" entry is gone. */}

      <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-faint)", letterSpacing: "0.02em", padding: "0 10px 8px" }}>{t("chrome.pages")}</div>
      <nav ref={navRef} data-tour="sidebar" style={{ position: "relative", display: "flex", flexDirection: "column", gap: 2 }}>
        <div ref={indRef} aria-hidden="true" style={{ position: "absolute", left: 0, right: 0, top: 0, height: 34, borderRadius: 8, background: "var(--ink-100)", zIndex: 0, opacity: 0, pointerEvents: "none", transition: "opacity .2s var(--ease-out)" }} />
        {NAV.map(it => <NavItem key={it.id} item={it} active={active === it.id} onClick={() => onNavigate(it.id)} count={it.countKey ? counts[it.countKey] : null} />)}
      </nav>

      <div style={{ flex: 1 }} />

      <button onClick={() => onNavigate("settings")} style={{ display: "flex", alignItems: "center", gap: 10, width: "100%", height: 34, padding: "0 10px",
        border: "none", borderRadius: 8, cursor: "pointer", background: active==="settings"?"var(--ink-100)":"transparent",
        color: active==="settings"?"var(--text-strong)":"var(--text-muted)", fontFamily: "var(--font-sans)", fontSize: 13.5, fontWeight: 500, marginBottom: 8 }}>
        <Icon name="settings" size={16} style={{ color: "var(--text-faint)" }} /> {t("nav.settings")}
      </button>

      {/* Reddit-mentions upsell, hidden once on a paid plan. Routes into
          Settings → Plan and highlights the Reddit-citations upgrade card. */}
      {!isPaid && (
        <div style={{ borderRadius: 10, padding: 12, background: "var(--ink-900)", color: "#fff" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 10 }}>
            <Icon name="message-square" size={14} style={{ color: "#fff", flex: "none" }} />
            <div style={{ fontSize: 12.5, fontWeight: 600 }}>{t("reddit.upsell.title")}</div>
          </div>
          <button onClick={() => { window.LTQ.settingsAnchor = "plan-reddit"; onNavigate("settings"); }} style={{ width: "100%", height: 30, borderRadius: 7, border: "none", cursor: "pointer", background: "#fff", color: "var(--ink-900)", fontFamily: "var(--font-sans)", fontSize: 12, fontWeight: 600 }}>{t("reddit.upsell.cta")}</button>
        </div>
      )}
    </aside>
  );
}
window.LTQ.Sidebar = Sidebar;
})();
