/* ========================================================================
   CHROME — AppSidebar + AppHeader + HelperTip
   Dynamic nav sections (recent searches, worksheets tree, agents list,
   role switch) and header actions are contributed by page modules via
   window hooks; the chrome renders them when present.
   ======================================================================== */

const PAGE_TITLES = {
  search: 'Search',
  opportunities: 'Opportunities',
  agents: 'Agents',
  territories: 'Territories',
  worksheets: 'Worksheets',
  account: 'Account',
  templates: 'Agent Templates',
  'custom-filters': 'Custom Filters',
  foia: 'FOIA',
  enrich: 'Enrich',
};

/* ---- Sidebar -----------------------------------------------------------
   Thin adapter over the Design System `SidebarNav` (codified component on
   window.PursuitDesignSystem2026_7f6065). The app's nav is data — we map
   live store state into `items` / `footerItems` / `user` / `footerSlot`
   each render, and route every selection through `onSelect`.

   Active highlight is driven by `activeItem`/`activeChild` props derived
   from the current page; the component self-syncs when they change (no
   remount needed for ordinary navigation). We additionally bump a remount
   `key` on every navigating select so a CANCELLED `guardLeaveAgent` (user
   clicked away from an unsaved agent draft, then backed out) snaps the
   highlight back to the true page instead of stranding on the attempt. -- */

// childId prefixes keep ids stable + collision-free across sections.
const SB_RS = 'rs:';        // recent search  → rs:<query>
const SB_WS = 'ws:';        // worksheet sheet → ws:<sheetId>
const SB_WBFIRST = 'wbfirst:'; // workbook folder → opens first sheet
const SB_AGENT = 'agent:';  // personal agent  → agent:<agentId>
const SB_INST = 'inst:';    // assigned instance → inst:<instanceId>

// Map the live store to the SidebarNav active selection.
function sbActiveSelection() {
  switch (state.page) {
    case 'search':        return { item: 'search', child: null };
    case 'opportunities': return { item: 'opportunities', child: null };
    case 'worksheets':    return { item: 'worksheets', child: state.worksheetId ? SB_WS + state.worksheetId : null };
    case 'agents':
      if (state.instanceId) return { item: 'agents', child: SB_INST + state.instanceId };
      if (state.agentId)    return { item: 'agents', child: SB_AGENT + state.agentId };
      return { item: 'agents', child: null };
    case 'territories':   return { item: 'company', child: 'territories' };
    case 'templates':     return { item: 'settings', child: 'agent-templates' };
    case 'custom-filters': return { item: 'settings', child: 'custom-filters' };
    case 'foia':          return { item: 'foia', child: null };
    case 'enrich':        return { item: 'enrich', child: null };
    default:              return { item: null, child: null }; // account → user block (no row)
  }
}

function AppSidebar() {
  useAppState();
  const { SidebarNav } = window.PursuitDesignSystem2026_7f6065 || {};
  // Remount nonce — bumped after every navigating select so the component
  // re-derives its highlight from props (covers guard-cancel; see header).
  const [navNonce, setNavNonce] = React.useState(0);
  const bump = React.useCallback(() => setNavNonce(n => n + 1), []);

  if (!SidebarNav) return <aside className="sidebar" />; // bundle not ready

  const RoleSwitch = window.RoleSwitch;
  const admin = (typeof isAdmin !== 'function') || isAdmin();
  const ident = (typeof currentIdentity === 'function')
    ? currentIdentity()
    : { name: 'Jordan Mateo', email: 'jordan@acme.com', initials: 'JM' };

  /* -- primary items (data derived from store) -- */
  const sheetChild = (s) => ({ label: s.name, icon: WS_ENTITY_ICON[s.type] || 'table-2', id: SB_WS + s.id });

  // Search → recent searches as always-open inline children (no chevron).
  const searchChildren = (RECENT_SEARCHES || []).map(q => ({ label: q, icon: 'search', id: SB_RS + q }));

  // Worksheets → current workbook (+ its sheets) and a "Recent" group.
  const wsGroups = [];
  const curSheet = state.worksheetId ? wsSheetById(state.worksheetId) : null;
  const curWbId = curSheet ? curSheet.wb : null;
  if (curSheet) {
    if (curWbId) {
      const wb = wsWorkbookById(curWbId) || {};
      wsGroups.push({ workbook: {
        label: wb.name || 'Workbook', icon: 'book', id: SB_WBFIRST + curWbId,
        children: wsSheetsInWorkbook(curWbId).map(sheetChild),
      } });
    } else {
      wsGroups.push({ children: [sheetChild(curSheet)] });
    }
  }
  const wsRecents = wsRecentViewed()
    .filter(id => id !== state.worksheetId)
    .map(wsSheetById)
    .filter(s => s && (!curWbId || s.wb !== curWbId))
    .slice(0, 4);
  if (wsRecents.length) wsGroups.push({ label: 'Recent', children: wsRecents.map(sheetChild) });

  // Agents → personal agents (admin) or assigned instances (member),
  // always inline (matches Mk7: the list is never page-gated).
  const me = admin ? null : currentMember();
  const mineAgents = agentsForUser(admin ? agentAdminId() : me.id);
  const myInsts = admin ? [] : instancesForUser(me.id);
  const agentChildren = [
    ...mineAgents.map(a => ({ label: a.name, id: SB_AGENT + a.id })),
    ...myInsts.map(inst => {
      const tpl = instanceTemplate(inst);
      return tpl ? { label: tpl.name, id: SB_INST + inst.id } : null;
    }).filter(Boolean),
  ];

  const items = [
    // Only attach `children` when non-empty — an empty array still reads as
    // truthy in the DS `childGroups`, which would render a phantom (empty,
    // ~8px) inline children container and break vertical rhythm vs collapsed.
    { label: 'Search', icon: 'search', id: 'search', expandable: false, ...(searchChildren.length ? { children: searchChildren } : {}) },
    { label: 'Opportunities', icon: 'briefcase', id: 'opportunities' },
    { label: 'Worksheets', icon: 'table-properties', id: 'worksheets', groups: wsGroups },
    { label: 'Agents', icon: 'bot-message-square', id: 'agents', lane: 'secondary', expandable: false, ...(agentChildren.length ? { children: agentChildren } : {}) },
    { label: 'FOIA', icon: 'eye', id: 'foia', lane: 'secondary' },
    { label: 'Enrich', icon: 'file-pen-line', id: 'enrich', lane: 'secondary' },
  ];

  /* -- footer items (admin only) -- */
  const footerItems = admin ? [
    { label: 'Company', icon: 'building-2', id: 'company', lane: 'tertiary', children: [
      { label: 'Users', icon: 'users', id: 'users' },
      { label: 'Territories', icon: 'map', id: 'territories' },
      { label: 'Manage Credits', icon: 'coins', id: 'manage-credits' },
      { label: 'Usage', icon: 'chart-line', id: 'usage' },
    ] },
    { label: 'Settings', icon: 'settings', id: 'settings', lane: 'tertiary', children: [
      { label: 'Agent Templates', icon: 'layout-template', id: 'agent-templates' },
      { label: 'Custom Filters', icon: 'filter', id: 'custom-filters' },
      { label: 'Integrations', icon: 'plug', id: 'integrations' },
      { label: 'Webhooks', icon: 'webhook', id: 'webhooks' },
    ] },
  ] : [];

  /* -- selection dispatch -- */
  // Wrap a navigation in the agent-draft guard, then force a resync so a
  // cancelled guard can't strand the highlight on the attempted target.
  const navGuard = (proceed) => { guardLeaveAgent(proceed); bump(); };

  const onSelect = ({ itemId, childId }) => {
    // ----- child rows -----
    if (childId != null) {
      if (childId.startsWith(SB_RS)) {
        const q = childId.slice(SB_RS.length);
        navGuard(() => {
          if (state.page !== 'search') switchPage('search');
          setTimeout(() => {
            if (window.__searchBar) window.__searchBar.setQuery(q);
            if (typeof runSmartParse === 'function') runSmartParse(q);
          }, 0);
        });
        return;
      }
      if (childId.startsWith(SB_WS) || childId.startsWith(SB_WBFIRST)) {
        let sheetId;
        if (childId.startsWith(SB_WBFIRST)) {
          const first = wsSheetsInWorkbook(childId.slice(SB_WBFIRST.length))[0];
          if (!first) { bump(); return; }
          sheetId = first.id;
        } else {
          sheetId = childId.slice(SB_WS.length);
        }
        navGuard(() => {
          state.worksheetRecord = null;
          state.worksheetId = sheetId;
          if (state.page !== 'worksheets') switchPage('worksheets'); else notify();
        });
        return;
      }
      if (childId.startsWith(SB_AGENT)) {
        const id = childId.slice(SB_AGENT.length);
        navGuard(() => {
          state.agentId = id; state.instanceId = null;
          if (state.page !== 'agents') switchPage('agents'); else notify();
        });
        return;
      }
      if (childId.startsWith(SB_INST)) {
        const id = childId.slice(SB_INST.length);
        navGuard(() => {
          state.instanceId = id; state.agentId = null;
          if (state.page !== 'agents') switchPage('agents'); else notify();
        });
        return;
      }
      if (childId === 'territories') {
        navGuard(() => { state.instanceId = null; state.agentId = null; switchPage('territories'); });
        return;
      }
      if (childId === 'agent-templates') {
        navGuard(() => { state.instanceId = null; state.agentId = null; switchPage('templates'); });
        return;
      }
      if (childId === 'custom-filters') {
        navGuard(() => { state.instanceId = null; state.agentId = null; openCustomFiltersList(); });
        return;
      }
      // Other footer children (Users, Manage Credits, Usage, Custom Filters,
      // Integrations, Webhooks) are inert placeholders — no navigation.
      return;
    }
    // ----- top-level / footer items -----
    // Company / Settings are pure accordion toggles (handled internally by
    // the component) — no navigation, no resync.
    if (itemId === 'company' || itemId === 'settings') return;

    if (itemId === 'agents') {
      navGuard(() => {
        state.agentId = null; state.instanceId = null;
        if (state.page === 'agents') notify(); else switchPage('agents');
      });
      return;
    }
    if (itemId === 'search' || itemId === 'opportunities' || itemId === 'worksheets' ||
        itemId === 'foia' || itemId === 'enrich') {
      navGuard(() => {
        if (state.page === itemId) {
          // Clicking the active page resets it to its initial state.
          if (itemId === 'search') {
            state.filters = [];
            state.activeSavedSearchId = null;
            state.openFieldId = null;
            state.editorAnchor = null;
            state.detailRecord = null;
            state.entity = 'accounts';
            if (window.__clearSearchInput) window.__clearSearchInput();
          } else if (itemId === 'opportunities') {
            state.inbox.selectedKey = null;
            state.detailRecord = null;
          } else if (itemId === 'worksheets') {
            state.worksheetId = null;
          }
          notify();
        } else {
          if (itemId === 'worksheets') state.worksheetId = null;
          switchPage(itemId);
        }
      });
      return;
    }
  };

  const active = sbActiveSelection();

  return (
    <SidebarNav
      key={navNonce}
      items={items}
      footerItems={footerItems}
      user={{ name: ident.name, email: ident.email, initials: ident.initials }}
      onUserClick={() => navGuard(() => { state.instanceId = null; state.agentId = null; switchPage('account'); })}
      footerSlot={RoleSwitch ? <RoleSwitch /> : null}
      collapseStore="ps-sidebar-collapsed"
      activeItem={active.item}
      activeChild={active.child}
      onSelect={onSelect}
    />
  );
}

/* ---- Header ------------------------------------------------------------ */

function DefaultBreadcrumbs() {
  useAppState();
  return (
    <div className="breadcrumbs">
      <img src={(window.__resources&&window.__resources.logoColor)||"react/assets/logo-color.svg"} alt="Pursuit" width="14" height="17" />
      <Icon name="chevron-right" className="breadcrumb-sep" size={14} />
      <span className="breadcrumb-item current">{PAGE_TITLES[state.page] || 'Pursuit'}</span>
    </div>
  );
}

function AppHeader() {
  useAppState();
  const Crumbs = (window.PAGE_BREADCRUMBS && window.PAGE_BREADCRUMBS[state.page]) || window.HeaderBreadcrumbs || DefaultBreadcrumbs;
  const SearchSlot = window.GlobalSearchSlot;
  const AccountActions = window.HeaderAccountActions;
  const TplActions = window.HeaderTplActions;
  const BulkActions = window.HeaderBulkActions;
  const SaveSplit = window.HeaderSaveSearchSplit;
  const CreateAgent = window.HeaderCreateAgentBtn;
  const PageActions = (window.PAGE_HEADER_ACTIONS && window.PAGE_HEADER_ACTIONS[state.page]) || null;
  const hideAskAI = !!(window.PAGE_NO_ASK_AI && window.PAGE_NO_ASK_AI[state.page]);
  return (
    <header className="global-header">
      <Crumbs />
      <div className="global-search-slot">{SearchSlot && state.page !== 'search' ? <SearchSlot /> : null}</div>
      <div className="header-actions">
        {AccountActions ? <AccountActions /> : null}
        {hideAskAI ? null : (
          <button className="btn-secondary-cta" type="button" data-testid="header-ask-ai"
            onClick={() => window.PursuitAgentPanel && window.PursuitAgentPanel.open()}>
            <span className="icon-frame"><Icon name="sparkles" size={16} /></span>
            Ask AI
          </button>
        )}
        {TplActions ? <TplActions /> : null}
        {BulkActions ? <BulkActions /> : null}
        {SaveSplit ? <SaveSplit /> : null}
        {CreateAgent ? <CreateAgent /> : null}
        {PageActions ? <PageActions /> : null}
      </div>
    </header>
  );
}

/* ---- Helper tip (fast tooltip for [data-helper-tip]) -------------------- */

function HelperTipLayer() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const tip = ref.current;
    let showTimer = null;
    let current = null;
    const move = (target) => {
      const r = target.getBoundingClientRect();
      tip.style.left = Math.min(r.left, window.innerWidth - tip.offsetWidth - 12) + 'px';
      tip.style.top = (r.bottom + 8) + 'px';
    };
    const over = (e) => {
      const t = e.target.closest && e.target.closest('[data-helper-tip]');
      if (!t || t === current) return;
      current = t;
      clearTimeout(showTimer);
      showTimer = setTimeout(() => {
        tip.hidden = false;
        tip.textContent = t.getAttribute('data-helper-tip') || '';
        move(t);
        requestAnimationFrame(() => tip.setAttribute('data-visible', 'true'));
      }, 250);
    };
    const out = (e) => {
      const t = e.target.closest && e.target.closest('[data-helper-tip]');
      if (!t || t !== current) return;
      current = null;
      clearTimeout(showTimer);
      tip.setAttribute('data-visible', 'false');
      tip.hidden = true;
    };
    document.addEventListener('mouseover', over);
    document.addEventListener('mouseout', out);
    return () => {
      document.removeEventListener('mouseover', over);
      document.removeEventListener('mouseout', out);
    };
  }, []);
  return <div id="helper-tip" ref={ref} hidden></div>;
}

Object.assign(window, { AppSidebar, AppHeader, HelperTipLayer, PAGE_TITLES });
