/* ========================================================================
   OPPORTUNITIES INBOX — records list (profiles picker, view chips,
   filters popover) + signal body. Port of 05-inbox.js.
   ======================================================================== */

function InboxFiltersPopover() {
  useAppState();
  const f = state.inbox.filters;
  const setF = (key, val) => {
    state.inbox.filters[key] = val;
    const visible = inboxSignals();
    const stillVisible = state.inbox.selectedKey && visible.some(s => signalRowKey(s) === state.inbox.selectedKey);
    if (!stillVisible) state.inbox.selectedKey = null;
    notify();
  };
  return (
    <div className="inbox-filters-popover" role="dialog" aria-label="Inbox filters">
      <div className="inbox-filters-head">
        <span>Filters</span>
        {inboxAnyFilterActive() ? (
          <button
            className="inbox-filters-clear" type="button"
            onClick={(e) => {
              e.stopPropagation();
              state.inbox.filters = { inboxZero: false, savedOnly: false, hideDone: false, showDismissed: false, hideTeamActions: false, dateFrom: '', dateTo: '' };
              notify();
            }}
          >Clear</button>
        ) : null}
      </div>
      <label className="inbox-filter-row">
        <input type="checkbox" checked={f.showDismissed} onChange={(e) => setF('showDismissed', e.target.checked)} />
        <span className="inbox-filter-row-text">
          <span className="inbox-filter-row-title">Show dismissed</span>
          <span className="inbox-filter-row-sub">Include signals you've thumbed down</span>
        </span>
      </label>
      <label className="inbox-filter-row">
        <input type="checkbox" checked={f.hideTeamActions} onChange={(e) => setF('hideTeamActions', e.target.checked)} />
        <span className="inbox-filter-row-text">
          <span className="inbox-filter-row-title">Hide team actions</span>
          <span className="inbox-filter-row-sub">Only show your own activity on the timeline</span>
        </span>
      </label>
      <div className="inbox-filter-section">Date range</div>
      <div className="inbox-filter-range">
        <label className="inbox-filter-date">
          <span>From</span>
          <input type="date" value={f.dateFrom || ''} onChange={(e) => setF('dateFrom', e.target.value)} />
        </label>
        <label className="inbox-filter-date">
          <span>To</span>
          <input type="date" value={f.dateTo || ''} onChange={(e) => setF('dateTo', e.target.value)} />
        </label>
      </div>
    </div>
  );
}

/* Body-level portal popover for the Account Profile combobox. */
function InboxProfileMenu({ anchorRef }) {
  useAppState();
  const menuRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const subs = state.inbox.profileSubs;
  const q = (state.inbox.profileQuery || '').trim().toLowerCase();
  const selectedList = [...subs];
  const available = TARGETS.map(t => t.name).filter(n => !subs.has(n));
  const matches = (q ? available.filter(n => n.toLowerCase().includes(q)) : available).slice(0, 20);

  React.useLayoutEffect(() => {
    const btn = anchorRef.current;
    const menu = menuRef.current;
    if (!btn || !menu) return;
    const r = btn.getBoundingClientRect();
    const desired = r.width * 1.5;
    const maxW = window.innerWidth - r.left - 12;
    const width = Math.min(desired, Math.max(r.width, maxW));
    menu.style.top = `${r.bottom + 4}px`;
    menu.style.left = `${r.left}px`;
    menu.style.width = `${width}px`;
  });
  React.useEffect(() => {
    if (inputRef.current) inputRef.current.focus();
  }, []);

  const afterChange = () => {
    const visible = inboxSignals();
    const stillVisible = state.inbox.selectedKey && visible.some(s => signalRowKey(s) === state.inbox.selectedKey);
    if (!stillVisible) state.inbox.selectedKey = null;
    notify();
    requestAnimationFrame(() => { if (inputRef.current) inputRef.current.focus(); });
  };
  const pick = (name) => { if (name) { state.inbox.profileSubs.add(name); state.inbox.profileQuery = ''; afterChange(); } };
  const unpick = (name) => { if (name) { state.inbox.profileSubs.delete(name); afterChange(); } };

  return ReactDOM.createPortal(
    <div id="inbox-profile-portal">
      <div className="inbox-profile-menu" role="dialog" aria-label="Choose Account Profiles" ref={menuRef}>
        <div className="ve-tag-area">
          {subs.size ?
          <div className="inbox-profile-head">
            <span className="inbox-profile-head-label">{subs.size} of {TARGETS.length} profiles</span>
            <button
              className="inbox-profile-clear" type="button"
              onClick={(e) => { e.stopPropagation(); state.inbox.profileSubs.clear(); state.inbox.profileQuery = ''; afterChange(); }}>Clear</button>
          </div> :
          null}
          <div className="ve-tag-chips">
            {selectedList.map(n => (
              <span className="ve-tag-chip" key={n}>
                <span>{n}</span>
                <button aria-label="Remove" onClick={(e) => { e.stopPropagation(); unpick(n); }}>×</button>
              </span>
            ))}
          </div>
          {available.length ?
          <React.Fragment>
          <input
            ref={inputRef}
            className="ve-input" type="text" autoComplete="off"
            placeholder={subs.size ? 'Add another profile…' : 'Type a profile — e.g. "Large K-12 districts"'}
            value={state.inbox.profileQuery || ''}
            onChange={(e) => { state.inbox.profileQuery = e.target.value; notify(); }}
            onKeyDown={(e) => {
              if (e.key === 'Escape') {
                state.inbox.profileOpen = false;
                state.inbox.profileQuery = '';
                notify();
              } else if (e.key === 'Enter') {
                if (matches[0]) { e.preventDefault(); pick(matches[0]); }
              } else if (e.key === 'Backspace' && !e.target.value && subs.size) {
                unpick([...subs].pop());
              }
            }}
          />
          <div className="ve-combo-list">
            {matches.length ? (
              <React.Fragment>
                {available.length ? (
                  <button
                    className="ve-combo-item ve-combo-item-meta" type="button"
                    onClick={(e) => {
                      e.stopPropagation();
                      TARGETS.forEach(t => state.inbox.profileSubs.add(t.name));
                      state.inbox.profileQuery = '';
                      afterChange();
                    }}
                  >
                    <span><strong>All Profiles</strong> <span className="ve-combo-meta-hint">— add every profile</span></span>
                  </button>
                ) : null}
                {matches.map(n => (
                  <button className="ve-combo-item" type="button" key={n} onClick={(e) => { e.stopPropagation(); pick(n); }}>
                    <span><HighlightMatch text={n} query={q} /></span>
                  </button>
                ))}
              </React.Fragment>
            ) : (
              <div className="ve-combo-empty">{q ? `No profiles match \u201c${q}\u201d.` : 'All profiles selected.'}</div>
            )}
          </div>
          </React.Fragment> :
          null}
        </div>
      </div>
    </div>,
    document.body
  );
}

function InboxRow({ s, selectedKey }) {
  const k = signalRowKey(s);
  const isUnread = state.inbox.unreadKeys.has(k);
  const isActive = k === selectedKey;
  const isDone = state.inbox.doneKeys.has(k);
  const isDismissed = state.inbox.dismissedKeys.has(k);
  const isSaved = state.inbox.savedKeys.has(k);
  const acctName = s.account?.name || '—';
  const date = formatSignalDate(s.date) || (s.daysAgo != null ? fmtDaysAgo(s.daysAgo).toUpperCase() : '');
  const synopsis = (s.text || s.name || '').slice(0, 180);
  return (
    <button
      className={cx('inbox-row', isActive && 'active', isUnread && 'unread')}
      type="button" data-inbox-key={k} data-agent-ref={'signals:' + k}
      onClick={() => {
        state.inbox.selectedKey = k;
        state.inbox.unreadKeys.delete(k);
        notify();
      }}
    >
      <span className="inbox-row-date">{date}</span>
      <span className="inbox-row-title">
        {isUnread ? <span className="inbox-unread-dot" aria-label="Unread"></span> : null}
        <span className="inbox-row-account">{acctName}</span>
      </span>
      <span className="inbox-row-synopsis">{synopsis}</span>
      {(isSaved || isDone || isDismissed) ? (
        <span className="inbox-row-status">
          {isSaved ? <span className="inbox-status inbox-status-saved"><Icon name="star" size={11} />Saved</span> : null}
          {isDone ? <span className="inbox-status inbox-status-done"><Icon name="check" size={11} />Done</span> : null}
          {isDismissed ? <span className="inbox-status inbox-status-dismissed"><Icon name="thumbs-down" size={11} />Dismissed</span> : null}
        </span>
      ) : null}
    </button>
  );
}

function InboxList() {
  useAppState();
  const profileBtnRef = React.useRef(null);
  const filterWrapRef = React.useRef(null);
  const list = inboxSignals().slice().sort(inboxSortFn);
  const subs = state.inbox.profileSubs;
  let activeProfile;
  if (subs.size === 0) activeProfile = 'No Profiles Selected';
  else if (subs.size >= TARGETS.length) activeProfile = 'All Profiles';
  else if (subs.size === 1) activeProfile = [...subs][0];
  else activeProfile = `${subs.size} profiles`;

  // Selected Profiles (ordered, color-indexed) shown as inline chips in the
  // trigger when 1..all-1 are picked. "All" / "None" keep a compact label.
  const selectedProfiles = TARGETS
    .map((t, i) => ({ name: t.name, colorIdx: i, tier: t.tier }))
    .filter(p => subs.has(p.name));
  const showChips = subs.size >= 1 && subs.size < TARGETS.length;
  const openProfileMenu = (e) => {
    e.stopPropagation();
    state.inbox.profileOpen = !state.inbox.profileOpen;
    state.inbox.filterOpen = false;
    if (!state.inbox.profileOpen) state.inbox.profileQuery = '';
    notify();
  };
  const removeProfile = (name) => {
    state.inbox.profileSubs.delete(name);
    const vis = inboxSignals({ ignorePin: true });
    if (state.inbox.selectedKey && !vis.some(s => signalRowKey(s) === state.inbox.selectedKey)) state.inbox.selectedKey = null;
    notify();
  };
  const midTruncate = (str, max) => {
    if (!str || str.length <= max) return str;
    const keep = max - 1, head = Math.ceil(keep / 2), tail = Math.floor(keep / 2);
    return str.slice(0, head) + '\u2026' + str.slice(str.length - tail);
  };

  // Outside-click dismissal for the toolbar popovers.
  React.useEffect(() => {
    const onDown = (e) => {
      if (!state.inbox.profileOpen && !state.inbox.filterOpen) return;
      const portal = document.getElementById('inbox-profile-portal');
      let changed = false;
      if (state.inbox.profileOpen
          && profileBtnRef.current && !profileBtnRef.current.contains(e.target)
          && !(portal && portal.contains(e.target))) {
        state.inbox.profileOpen = false;
        state.inbox.profileQuery = '';
        changed = true;
      }
      if (state.inbox.filterOpen && filterWrapRef.current && !filterWrapRef.current.contains(e.target)) {
        state.inbox.filterOpen = false;
        changed = true;
      }
      if (changed) notify();
    };
    document.addEventListener('mousedown', onDown, true);
    return () => document.removeEventListener('mousedown', onDown, true);
  }, []);

  const toggleView = (id) => {
    if (state.inbox.viewSegments.has(id)) state.inbox.viewSegments.delete(id);
    else state.inbox.viewSegments.add(id);
    const visible = inboxSignals({ ignorePin: true });
    const stillVisible = state.inbox.selectedKey && visible.some(s => signalRowKey(s) === state.inbox.selectedKey);
    if (!stillVisible) state.inbox.selectedKey = null;
    notify();
  };

  return (
    <div className="records-nav" id="records-nav">
      <div className="inbox-toolbar">
        <div className="inbox-profile-wrap">
          <button
            ref={profileBtnRef}
            className="inbox-profile-btn" type="button"
            onClick={openProfileMenu}>
            <Icon name="box" size={14} className="inbox-profile-glyph" />
            <span className="inbox-profile-label">{activeProfile}</span>
            <Icon name="chevrons-up-down" size={14} className="inbox-profile-chev" />
          </button>
        </div>
        <div className="inbox-filter-wrap" ref={filterWrapRef}>
          <button
            className={cx('inbox-filter-btn', inboxAnyFilterActive() && 'active')} type="button" aria-label="More filters"
            onClick={(e) => {
              e.stopPropagation();
              state.inbox.filterOpen = !state.inbox.filterOpen;
              state.inbox.profileOpen = false;
              notify();
            }}
          >
            <Icon name="sliders-horizontal" size={14} />
            {inboxAnyFilterActive() ? <span className="inbox-filter-dot" aria-hidden="true"></span> : null}
          </button>
          {state.inbox.filterOpen ? <InboxFiltersPopover /> : null}
        </div>
      </div>
      <div className="inbox-views" role="group" aria-label="Inbox view filters">
        <span className="inbox-views-label">Only show:</span>
        {[
          { id: 'unread', label: 'Unread' },
          { id: 'saved', label: 'Saved' },
          { id: 'todo', label: 'To Do' },
        ].map(v => (
          <button
            key={v.id}
            className={cx('inbox-view-chip', state.inbox.viewSegments.has(v.id) && 'active')}
            type="button" aria-pressed={state.inbox.viewSegments.has(v.id)}
            onClick={() => toggleView(v.id)}
          >{v.label}</button>
        ))}
      </div>
      <div className="inbox-list">
        {subs.size === 0 ? (
          <div className="rn-empty inbox-empty-noprofile">No Account Profiles selected.<br /><span>Add a profile from the picker above to see opportunities.</span></div>
        ) : list.length ? (
          list.map(s => <InboxRow s={s} selectedKey={state.inbox.selectedKey} key={signalRowKey(s)} />)
        ) : (
          <div className="rn-empty">No opportunities match this view.</div>
        )}
      </div>
      {state.inbox.profileOpen ? <InboxProfileMenu anchorRef={profileBtnRef} /> : null}
    </div>
  );
}

function InboxBody() {
  useAppState();
  const loopRef = React.useRef(null);
  const sel = state.inbox.selectedKey;
  const s = sel ? SIGNALS.find(x => signalRowKey(x) === sel) : null;
  const [bodyQuery, setBodyQuery] = React.useState('');
  // Switching signals should always show the new content from the top —
  // reset the scroll container rather than keeping the prior position.
  React.useEffect(() => {
    const cp = document.querySelector('.content-panel');
    if (cp) cp.scrollTop = 0;
  }, [sel]);

  // Hide the lens-loop magnifier in the inbox empty state.
  React.useEffect(() => {
    if (s) return;
    const host = loopRef.current;
    if (!host) return;
    const loop = host.querySelector('pursuit-lens-loop');
    if (!loop) return;
    const hideMag = () => {
      const root = loop.shadowRoot;
      if (!root || root.querySelector('style[data-no-mag]')) return;
      const st = document.createElement('style');
      st.setAttribute('data-no-mag', '');
      st.textContent = '.magnifier { display: none !important; }';
      root.appendChild(st);
    };
    requestAnimationFrame(hideMag);
  }, [!!s]);

  if (!s) {
    return (
      <div data-role="inbox" ref={loopRef}>
        <div className="empty-prompt">
          <div className="ep-anim"><pursuit-lens-loop dwell-min="2400" dwell-max="3600"></pursuit-lens-loop></div>
          <div className="ep-title">Your Opportunities inbox</div>
          <div className="ep-body">Pick an opportunity from the list to see its details.</div>
        </div>
      </div>
    );
  }
  return (
    <div data-role="inbox">
      <DetailHeader entity="signals" record={s} />
      <div className="inbox-search-row">
        <div className="inbox-body-search">
          <Icon name="search" size={14} />
          <input
            type="text" placeholder="Search in these Signals..."
            value={bodyQuery}
            onChange={(e) => setBodyQuery(e.target.value)} />
          {bodyQuery ?
          <button className="inbox-body-search-clear" type="button" aria-label="Clear search"
            onClick={() => setBodyQuery('')}><Icon name="x" size={14} /></button> :
          null}
        </div>
        <DraftEmailSplit />
        <button className="btn-secondary-cta">
          <span className="icon-frame"><Icon name="sparkles" size={16} /></span>
          Chat about Account
        </button>
      </div>
      <div className="detail-body">
        <AccountTimeline account={s.account} pinnedSignal={s} query={bodyQuery} />
      </div>
    </div>
  );
}

/* ---- account activity timeline (signals + activity rows interleaved) ------- */
function ActivityRow({ act }) {
  React.useEffect(() => { if (window.lucide) { try { lucide.createIcons(); } catch (e) {} } });
  const html = window.PursuitActivity ? PursuitActivity.renderActivityBanner(act) : '';
  return <div style={{ display: 'contents' }} dangerouslySetInnerHTML={{ __html: html }}></div>;
}

function AccountTimeline({ account, pinnedSignal, query }) {
  useAppState();
  if (!account) return null;
  const q = (query || '').trim().toLowerCase();
  // Scope the timeline to the currently-selected Profiles: a signal shows
  // only if the signal itself matches one of the subscribed Profiles (the
  // pinned/selected signal always shows).
  const subs = state.inbox.profileSubs;
  const scoped = (state.page === 'opportunities' || state.page === 'saved-opportunities') && subs && subs.size;
  const pinnedKey = pinnedSignal ? signalRowKey(pinnedSignal) : null;
  const profMatches = (sig) => {
    if (!scoped) return true;
    if (signalRowKey(sig) === pinnedKey) return true;
    return matchingProfilesFor(sig, account).some(p => subs.has(p.name));
  };
  const sigMatches = (sig) => {
    if (!q) return true;
    const hay = [sig.name, sig.text, sig.sigType, (sig.themes || []).join(' ')]
      .filter(Boolean).join(' ').toLowerCase();
    return hay.includes(q);
  };
  const actMatches = (a) => {
    if (!q) return true;
    try { return JSON.stringify(a).toLowerCase().includes(q); } catch (e) { return false; }
  };
  if (!window.PursuitActivity) {
    return sigMatches(pinnedSignal)
      ? <SignalCard s={pinnedSignal} sourceAccount={account} rich />
      : <div className="inbox-body-empty">No signals match “{query}”.</div>;
  }
  const hideTeam = state.inbox.filters.hideTeamActions;
  const items = [];
  (account.signals || []).forEach(sig => {
    if (hideTeam && PursuitActivity.hasTeamActivity(account.accountId, sig.name || sig.sigType)) return;
    if (!profMatches(sig)) return;
    if (!sigMatches(sig)) return;
    items.push({ kind: 'signal', date: sig.date || '', s: sig });
  });
  PursuitActivity.accountActivities(account.accountId).forEach(a => {
    if (hideTeam && a.actor) return;
    if (!actMatches(a)) return;
    items.push({ kind: 'activity', date: a.date || '', a });
  });
  items.sort((x, y) => {
    if (x.date !== y.date) return x.date < y.date ? 1 : -1;
    if (x.kind !== y.kind) return x.kind === 'activity' ? -1 : 1;
    return 0;
  });
  if (!items.length) {
    return <div className="inbox-body-empty">No signals or activity match “{query}”.</div>;
  }
  return (
    <React.Fragment>
      {items.map((it, i) => it.kind === 'signal'
        ? <SignalCard key={'s' + i} s={it.s} sourceAccount={account} rich />
        : <ActivityRow key={'a' + i} act={it.a} />)}
    </React.Fragment>
  );
}

function InboxPage() {
  useAppState();

  // Keyboard ↑/↓ moves the inbox selection.
  React.useEffect(() => {
    const onKey = (e) => {
      if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') return;
      if (e.metaKey || e.ctrlKey || e.altKey) return;
      const ae = document.activeElement;
      if (ae && ae !== document.body) {
        const tag = ae.tagName;
        if (tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT') return;
        if (ae.isContentEditable) return;
      }
      const rows = Array.from(document.querySelectorAll('.inbox-row[data-inbox-key]'));
      if (!rows.length) return;
      e.preventDefault();
      const idx = rows.findIndex(r => r.dataset.inboxKey === state.inbox.selectedKey);
      let next;
      if (idx < 0) next = e.key === 'ArrowDown' ? rows[0] : rows[rows.length - 1];
      else {
        let n = idx + (e.key === 'ArrowDown' ? 1 : -1);
        if (n < 0) n = 0;
        if (n >= rows.length) n = rows.length - 1;
        if (n === idx) return;
        next = rows[n];
      }
      state.inbox.selectedKey = next.dataset.inboxKey;
      state.inbox.unreadKeys.delete(next.dataset.inboxKey);
      notify();
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, []);

  const landing = !state.inbox.selectedKey || !SIGNALS.find(x => signalRowKey(x) === state.inbox.selectedKey);

  return (
    <div className="body">
      {landing ? <LandingParallelo /> : null}
      <div className="floating-widget-spacer">
        <div className="floating-widget">
          <InboxList />
        </div>
      </div>
      <div className="content-panel">
        <div id="work-area">
          <InboxBody />
        </div>
      </div>
    </div>
  );
}

/* ---- breadcrumbs ------------------------------------------------------------ */
function InboxBreadcrumbs() {
  useAppState();
  const isSaved = state.page === 'saved-opportunities';
  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} />
      {isSaved ? (
        <React.Fragment>
          <button className="breadcrumb-link" type="button" onClick={() => switchPage('opportunities')}>Inbox</button>
          <Icon name="chevron-right" className="breadcrumb-sep" size={14} />
          <span className="breadcrumb-item current">Saved</span>
        </React.Fragment>
      ) : (
        <span className="breadcrumb-item current">Inbox</span>
      )}
    </div>
  );
}

/* ---- global-header search slot (inbox / worksheets / agents) ------------------ */
function GlobalSearchSlot() {
  useAppState();
  const [value, setValue] = React.useState('');
  return <SearchBar value={value} setValue={setValue} />;
}

seedInbox();
window.PAGES.opportunities = InboxPage;
window.PAGES['saved-opportunities'] = InboxPage;
window.PAGE_BREADCRUMBS = window.PAGE_BREADCRUMBS || {};
window.PAGE_BREADCRUMBS.opportunities = InboxBreadcrumbs;
window.PAGE_BREADCRUMBS['saved-opportunities'] = InboxBreadcrumbs;
Object.assign(window, { InboxPage, InboxList, InboxBody, InboxBreadcrumbs, GlobalSearchSlot });
