// shell.jsx — App frame: LangProvider, Sidebar, Topbar (search palette +
// notifications), SubNav, router. Matches the latest Claude Design IA:
// 6 flat nav sections with operations consolidated into subtabs
// (Contacts → Leads/Escalations/Custom requests, Campaigns → Campaigns/Queue).
const { useState: useStateS, useEffect: useEffectS } = React;

const NAV_ITEMS = [
  { key: "dashboard", icon: "grid", label: "nav_dashboard" },
  { key: "contacts", icon: "users", label: "nav_contacts", subs: ["escalations", "requests"] },
  { key: "campaigns", icon: "megaphone", label: "nav_campaigns", subs: ["queue"] },
  { key: "conversations", icon: "message", label: "nav_conversations", badge: "pendingApprovals" },
  { key: "agents", icon: "bot", label: "nav_agents" },
  { key: "settings", icon: "settings", label: "nav_settings" },
];

// secondary tabs consolidating the lead-domain + campaign-delivery views into
// existing screens (no extra top-level nav). Counts are live (see App.opsCounts).
const SUBTABS = {
  contacts: [
    { route: "contacts", label: "Leads" },
    { route: "escalations", label: "Escalations", count: "escalationsOpen" },
    { route: "requests", label: "Custom requests", count: "requestsNew" },
  ],
  escalations: "contacts", requests: "contacts",
  campaigns: [
    { route: "campaigns", label: "Campaigns" },
    { route: "queue", label: "Messaging queue", count: "queueInFlight" },
  ],
  queue: "campaigns",
};
function subGroupFor(route) {
  const v = SUBTABS[route];
  if (!v) return null;
  return typeof v === "string" ? SUBTABS[v] : v;
}
function SubNav({ route, go, counts }) {
  const tabs = subGroupFor(route);
  if (!tabs) return null;
  return (
    <div className="subnav">
      {tabs.map((tb) => {
        const n = tb.count ? (counts[tb.count] || 0) : 0;
        return (
          <button key={tb.route} className={"subnav__tab" + (route === tb.route ? " is-active" : "")} onClick={() => go(tb.route)}>
            {tb.label}
            {n ? <span className="subnav__count">{n}</span> : null}
          </button>
        );
      })}
    </div>
  );
}

const TWEAK_DEFAULTS = { accent: "#C7F262", density: "comfortable", crmView: "list", radius: 16 };

const AppCtx = React.createContext(null);
function useApp() { return React.useContext(AppCtx); }

function Sidebar({ route, go, open }) {
  const { t } = useLang();
  const data = useStore();
  const sessions = data.SESSIONS || [];
  const connected = sessions.filter((s) => s.state === "connected").length;
  return (
    <aside className={"sidebar" + (open ? " is-open" : "")}>
      <div className="sidebar__brand">
        <img src="assets/logo-dark.png" alt="Maxab Hub" />
      </div>
      <div style={{ padding: "0 16px 4px" }}>
        <div style={{ fontSize: 11, fontWeight: 700, letterSpacing: ".08em", textTransform: "uppercase", color: "var(--fg-disabled)" }}>{t("appName")}</div>
      </div>
      <nav className="sidebar__nav">
        {NAV_ITEMS.map((it) => {
          const active = route === it.key || (it.subs && it.subs.includes(route));
          const count = it.badge ? (data.meta?.[it.badge] || 0) : it.count;
          return (
            <button key={it.key} className={"navitem" + (active ? " is-active" : "")} onClick={() => go(it.key)}>
              <Icon name={it.icon} size={19} />
              <span>{t(it.label)}</span>
              {count ? <span className="navitem__count">{count}</span> : null}
            </button>
          );
        })}
      </nav>
      <div className="sidebar__foot">
        <button className="navitem" style={{ marginBottom: 8 }} onClick={() => go("settings")}>
          <span className="sdot" style={{ background: connected ? "#22C55E" : "#9CA3AF" }} />
          <span style={{ fontSize: 13, fontWeight: 600 }}>{t("connected")}</span>
          <span style={{ marginInlineStart: "auto", fontSize: 11, color: "var(--fg-4)" }}>{connected} lines</span>
        </button>
        <div className="row" style={{ padding: "4px 4px 0" }}>
          <Avatar name={data.meta?.user?.name || "Operator"} size="sm" />
          <div style={{ lineHeight: 1.2, minWidth: 0 }}>
            <div style={{ fontSize: 13, fontWeight: 600 }}>{data.meta?.user?.name || "Operator"}</div>
            <div style={{ fontSize: 11, color: "var(--fg-4)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", textTransform: "capitalize" }}>{data.meta?.user?.role || "Sales operator"}</div>
          </div>
          {data.meta?.authEnabled && (
            <button className="iconbtn" style={{ marginInlineStart: "auto", width: 32, height: 32 }} title="Sign out"
              onClick={() => { API.auth.logout().then(() => location.reload()).catch(() => location.reload()); }}><Icon name="logout" size={16} /></button>
          )}
        </div>
      </div>
    </aside>
  );
}

function Topbar({ route, onNew, onImport, go, onSearch, notifUnread, onMenu }) {
  const { t, lang, setLang } = useLang();
  const [notifOpen, setNotifOpen] = useStateS(false);
  const titles = {
    dashboard: ["nav_dashboard", "sub_dashboard"], contacts: ["nav_contacts", "sub_contacts"],
    campaigns: ["nav_campaigns", "sub_campaigns"], conversations: ["nav_conversations", "sub_conversations"],
    agents: ["nav_agents", "sub_agents"], settings: ["nav_settings", "sub_settings"],
    queue: ["nav_campaigns", "sub_queue"], escalations: ["nav_contacts", "sub_escalations"], requests: ["nav_contacts", "sub_requests"],
  };
  const [title, sub] = titles[route] || titles.dashboard;
  return (
    <header className="topbar">
      <button className="topbar__menu iconbtn" title="Menu" onClick={onMenu}><Icon name="menu" size={20} /></button>
      <div style={{ minWidth: 0 }}>
        <div className="topbar__title">{t(title)}</div>
        <div className="topbar__sub">{t(sub)}</div>
      </div>
      <div className="topbar__spacer" />
      <button className="search" onClick={onSearch} style={{ cursor: "text" }}>
        <Icon name="search" size={18} />
        <span style={{ flex: 1, textAlign: "start", fontSize: "var(--fs-body-sm)", color: "var(--fg-disabled)" }}>{t("search")}</span>
        <span className="kbd">⌘K</span>
      </button>
      <div className="seg" title="Language">
        <button className={lang === "en" ? "is-on" : ""} onClick={() => setLang("en")}>EN</button>
        <button className={lang === "ar" ? "is-on" : ""} onClick={() => setLang("ar")} style={{ fontFamily: "var(--font-arabic)" }}>ع</button>
      </div>
      <div style={{ position: "relative" }}>
        <button className="iconbtn" title="Notifications" onClick={() => setNotifOpen((v) => !v)}><Icon name="bell" size={20} />{notifUnread > 0 && <span className="iconbtn__dot" />}</button>
        {notifOpen && <NotificationsPanel onClose={() => setNotifOpen(false)} go={go} />}
      </div>
      {(route === "contacts") && <Button variant="ghost" icon="upload" onClick={onImport}>{t("import")}</Button>}
      <Button variant="primary" icon="plus" onClick={onNew}>{t("newCampaign")}</Button>
    </header>
  );
}

// notification type → icon/color/action label. `route` comes from the API record.
const NOTIF_TYPES = {
  approval:       { icon: "checkcircle", c: "var(--color-secondary)", action: "Open conversation" },
  reply:          { icon: "message", c: "var(--color-purple)", action: "Open conversation" },
  failed_send:    { icon: "alert", c: "var(--color-danger)", action: "Open queue job" },
  sender_limit:   { icon: "phoneDevice", c: "var(--color-orange)", action: "View sender" },
  escalation:     { icon: "alert", c: "var(--color-orange)", action: "Open escalation" },
  custom_request: { icon: "tag", c: "var(--color-purple)", action: "Open request" },
  followup:       { icon: "clock", c: "var(--color-blue)", action: "Open lead" },
  workflow:       { icon: "zap", c: "var(--color-danger)", action: "View details" },
};
function NotificationsPanel({ onClose, go }) {
  const [items, setItems] = useStateS([]);
  const [tab, setTab] = useStateS("all");
  const [loading, setLoading] = useStateS(true);
  const [err, setErr] = useStateS(null);

  useEffectS(() => {
    let alive = true;
    API.notifications()
      .then((r) => { if (alive) { setItems(r.notifications || []); setLoading(false); } })
      .catch((e) => { if (alive) { setErr(e.message || "Failed to load"); setLoading(false); } });
    return () => { alive = false; };
  }, []);
  useEffectS(() => {
    const h = (e) => { if (!e.target.closest("[data-notif]")) onClose(); };
    setTimeout(() => document.addEventListener("click", h), 0);
    return () => document.removeEventListener("click", h);
  }, [onClose]);

  const shown = tab === "unread" ? items.filter((n) => !n.read) : items;
  const unreadCount = items.filter((n) => !n.read).length;
  const markAll = () => { setItems((xs) => xs.map((n) => ({ ...n, read: true }))); API.markNotificationsRead({ all: true }).catch(() => {}); };
  const open = (n) => { setItems((xs) => xs.map((x) => x.id === n.id ? { ...x, read: true } : x)); API.markNotificationsRead({ ids: [n.id] }).catch(() => {}); go && go(n.route); onClose(); };

  return (
    <div data-notif style={{ position: "absolute", top: 48, insetInlineEnd: 0, width: 392, background: "#fff", borderRadius: "var(--radius-lg)", boxShadow: "var(--shadow-xl)", border: "1px solid var(--border-1)", zIndex: 60, overflow: "hidden" }}>
      <div className="between" style={{ padding: "14px 16px", borderBottom: "1px solid var(--border-1)" }}>
        <div className="row" style={{ gap: 8 }}><b style={{ fontSize: 14 }}>Notifications</b>{unreadCount > 0 && <Badge tone="dark">{unreadCount}</Badge>}</div>
        <button className="btn btn--subtle btn--sm" onClick={markAll} disabled={unreadCount === 0}>Mark all read</button>
      </div>
      <div className="row" style={{ gap: 4, padding: "10px 16px 0" }}>
        <div className="seg">
          <button className={tab === "all" ? "is-on" : ""} onClick={() => setTab("all")}>All</button>
          <button className={tab === "unread" ? "is-on" : ""} onClick={() => setTab("unread")}>Unread</button>
        </div>
      </div>
      <div style={{ maxHeight: 420, overflowY: "auto", padding: "8px 0" }}>
        {loading ? <div style={{ padding: 16 }}><div className="skel" style={{ height: 60, borderRadius: 10, marginBottom: 8 }} /><div className="skel" style={{ height: 60, borderRadius: 10 }} /></div>
          : err ? <div style={{ textAlign: "center", padding: "28px 16px", color: "var(--color-danger)", fontSize: 13 }}><Icon name="alert" size={22} /><div style={{ marginTop: 6 }}>{err}</div></div>
          : shown.length === 0
            ? <div style={{ textAlign: "center", padding: "32px 16px", color: "var(--fg-4)" }}><Icon name="checkcircle" size={28} style={{ color: "var(--color-success)" }} /><div style={{ fontSize: 13, fontWeight: 600, color: "var(--fg-2)", marginTop: 8 }}>You're all caught up</div></div>
            : shown.map((n) => {
                const m = NOTIF_TYPES[n.type] || { icon: "bell", c: "var(--fg-3)", action: "Open" };
                return (
                  <div key={n.id} style={{ display: "flex", gap: 12, padding: "10px 16px", background: !n.read ? "var(--color-primary-tint-soft)" : "#fff", borderBottom: "1px solid var(--border-1)" }}>
                    <span className="opp" style={{ width: 34, height: 34, borderRadius: 10, background: "var(--bg-2)", color: m.c, flexShrink: 0 }}><Icon name={m.icon} size={17} /></span>
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontSize: 13, fontWeight: 700 }}>{n.title}</div>
                      <div style={{ fontSize: 12, color: "var(--fg-3)", marginTop: 1 }}>{n.body}</div>
                      <div className="row" style={{ gap: 10, marginTop: 6 }}>
                        <button onClick={() => open(n)} style={{ fontSize: 12, fontWeight: 700, color: "var(--color-secondary)", background: "none", border: "none", cursor: "pointer", padding: 0 }}>{m.action} →</button>
                      </div>
                    </div>
                    {!n.read && <span className="sdot" style={{ background: "var(--color-secondary)", marginTop: 6 }} />}
                  </div>
                );
              })}
      </div>
    </div>
  );
}

function App() {
  const [lang, setLang] = useStateS("en");
  const [route, setRoute] = useStateS("dashboard");
  const [drawer, setDrawer] = useStateS(null);     // { type, payload }
  const [overlay, setOverlay] = useStateS(null);    // wizard/import full-screen
  const [searchOpen, setSearchOpen] = useStateS(false);
  const [navOpen, setNavOpen] = useStateS(false); // mobile sidebar drawer
  const [opsCounts, setOpsCounts] = useStateS({ escalationsOpen: 0, requestsNew: 0, queueInFlight: 0, notifUnread: 0 });
  const [tweaks, setTweaks] = useTweaks(TWEAK_DEFAULTS);

  // ⌘K opens the command palette
  useEffectS(() => {
    const h = (e) => { if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") { e.preventDefault(); setSearchOpen(true); } };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, []);

  // live subtab counts (escalations open / custom requests new / queue in-flight)
  const refreshCounts = React.useCallback(() => {
    Promise.allSettled([
      API.escalations.list("status=open"),
      API.customRequests.list("status=new"),
      API.messaging.metrics(),
      API.notifications(),
    ]).then(([e, r, m, n]) => setOpsCounts({
      escalationsOpen: e.status === "fulfilled" ? (e.value.count ?? (e.value.escalations || []).length) : 0,
      requestsNew: r.status === "fulfilled" ? (r.value.count ?? (r.value.requests || []).length) : 0,
      queueInFlight: m.status === "fulfilled" ? (m.value.inFlight || 0) : 0,
      notifUnread: n.status === "fulfilled" ? (n.value.unread ?? (n.value.notifications || []).filter((x) => !x.read).length) : 0,
    }));
  }, []);
  useEffectS(() => { refreshCounts(); }, [refreshCounts]);
  // refresh when entering an ops area so badges reflect the latest
  useEffectS(() => { if (["contacts", "escalations", "requests", "campaigns", "queue"].includes(route)) refreshCounts(); }, [route, refreshCounts]);

  useEffectS(() => {
    document.documentElement.setAttribute("dir", lang === "ar" ? "rtl" : "ltr");
    document.documentElement.setAttribute("lang", lang);
  }, [lang]);

  useEffectS(() => {
    document.documentElement.style.setProperty("--color-primary", tweaks.accent);
    document.documentElement.style.setProperty("--app-radius", (tweaks.radius || 16) + "px");
  }, [tweaks.accent, tweaks.radius]);

  const t = (k) => (STRINGS[lang] && STRINGS[lang][k]) || (STRINGS.en[k]) || k;
  const langValue = { lang, setLang, t, dir: lang === "ar" ? "rtl" : "ltr" };

  const go = (r) => { setRoute(r); setDrawer(null); };
  const openContact = (c) => setDrawer({ type: "contact", payload: c });
  const openAgent = (a) => setDrawer({ type: "agent", payload: a });
  const startWizard = (preset) => setOverlay({ type: "wizard", payload: preset || null });
  const startImport = () => setOverlay({ type: "import" });
  const startRetarget = () => { setDrawer(null); setOverlay({ type: "retarget" }); };
  const editAgent = (a) => { setDrawer(null); setOverlay({ type: "agentEdit", payload: a }); };
  const newAgent = () => { setDrawer(null); setOverlay({ type: "agentEdit", payload: null }); };

  const appActions = { go, openContact, openAgent, startWizard, startImport, startRetarget, editAgent, newAgent, tweaks, setTweaks, route };

  return (
    <LangContext.Provider value={langValue}>
      <AppCtx.Provider value={appActions}>
        <div className="app" data-density={tweaks.density}>
          <Sidebar route={route} go={(r) => { go(r); setNavOpen(false); }} open={navOpen} />
          {navOpen && <div className="nav-scrim" onClick={() => setNavOpen(false)} />}
          <div className="main">
            <Topbar route={route} onNew={startWizard} onImport={startImport} go={go} onSearch={() => setSearchOpen(true)} notifUnread={opsCounts.notifUnread} onMenu={() => setNavOpen(true)} />
            <SubNav route={route} go={go} counts={opsCounts} />
            <div className="content" key={route}>
              {route === "dashboard" && <DashboardScreen />}
              {route === "contacts" && <ContactsScreen />}
              {route === "campaigns" && <CampaignsScreen />}
              {route === "conversations" && <ConversationsScreen />}
              {route === "agents" && <AgentsScreen />}
              {route === "queue" && <MessagingQueueScreen />}
              {route === "escalations" && <EscalationsScreen />}
              {route === "requests" && <CustomRequestsScreen />}
              {route === "settings" && <SettingsScreen />}
            </div>
          </div>

          {drawer?.type === "contact" && <ContactDrawer contact={drawer.payload} onClose={() => setDrawer(null)} />}
          {drawer?.type === "agent" && <AgentDrawer agent={drawer.payload} onClose={() => setDrawer(null)} />}
          {overlay?.type === "wizard" && <CampaignWizard preset={overlay.payload} onClose={() => setOverlay(null)} />}
          {overlay?.type === "import" && <ImportWizard onClose={() => setOverlay(null)} onCreateCampaign={(grp) => setOverlay({ type: "wizard", payload: { group: grp, goal: "shopify" } })} />}
          {overlay?.type === "retarget" && <RetargetOverlay onClose={() => setOverlay(null)} onCreateCampaign={(grp) => setOverlay({ type: "wizard", payload: { group: grp, goal: "retarget" } })} />}
          {overlay?.type === "agentEdit" && <AgentEditOverlay agent={overlay.payload} onClose={() => setOverlay(null)} />}
          {searchOpen && <SearchPalette go={go} openContact={openContact} openAgent={openAgent} onClose={() => setSearchOpen(false)} />}
        </div>
        <TweaksPanelMount />
      </AppCtx.Provider>
    </LangContext.Provider>
  );
}

window.App = App;
window.useApp = useApp;
