/* Inbox, Candidates, Requisitions, Interviews, Reports pages */

/* ─────────────── shared page shell ─────────────── */

/* Hash helpers — view + optional id after `/` (e.g. "candidates/abc-123") */
function _parseHash() {
  const h = window.location.hash.replace(/^#/, '');
  const [view, id] = h.split('/');
  return { view: view || 'dashboard', id: id || null };
}
function _setHashId(view, id) {
  window.location.hash = id ? `${view}/${id}` : view;
}

function PageShell({ active, onNav, title, children, onSearch, onSettings }) {
  const [searchOpen, setSearchOpen] = React.useState(false);
  const [settingsOpen, setSettingsOpen] = React.useState(false);
  const [candidate, setCandidate] = React.useState(null);

  // Use the rich Kanban drawer if loaded — same UX everywhere; fall back to
  // the simpler CandidateDrawer only if pipeline.jsx hasn't initialized yet.
  const PD  = window.PipelineDrawer;
  const oppId = candidate?.id || null;

  // Sync candidate state ↔ URL hash for shareable links.
  const openCandidate = React.useCallback((c) => {
    setCandidate(c);
    _setHashId(active, c?.id || null);
  }, [active]);
  const closeCandidate = React.useCallback(() => {
    setCandidate(null);
    _setHashId(active, null);
  }, [active]);

  // On mount + on hashchange, sync drawer state from URL — supports shared links.
  React.useEffect(() => {
    const sync = () => {
      const { view, id } = _parseHash();
      if (view !== active) return;
      if (id && (!candidate || candidate.id !== id)) {
        setCandidate({ id });
      } else if (!id && candidate) {
        setCandidate(null);
      }
    };
    sync();
    window.addEventListener('hashchange', sync);
    return () => window.removeEventListener('hashchange', sync);
  }, [active, candidate]);

  React.useEffect(() => {
    const fn = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); setSearchOpen(true); }
      if (e.key === 'Escape') { setSearchOpen(false); setSettingsOpen(false); closeCandidate(); }
    };
    window.addEventListener('keydown', fn);
    return () => window.removeEventListener('keydown', fn);
  }, [closeCandidate]);

  // PipelineDrawer hands us either an opp object {id, ...} or a bare id —
  // normalize before hitting the API.
  const _oppId = (x) => (x && typeof x === 'object' ? x.id : x);

  const movePipelineCandidate = React.useCallback((oppOrId, toStageId) => {
    const id = _oppId(oppOrId);
    if (!id) return;
    fetch(`/api/opportunities/${id}/stage`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ stageId: toStageId }),
    })
      .then(r => {
        if (!r.ok) throw new Error(`HTTP ${r.status}`);
        closeCandidate();
        window.location.reload();
      })
      .catch(err => { console.error('[ATS] stage move failed', err); alert('Stage move failed — see console.'); });
  }, [closeCandidate]);

  const rejectPipelineCandidate = React.useCallback((oppOrId) => {
    if (!confirm('Are you sure?')) return;
    movePipelineCandidate(oppOrId, 'rejected');
  }, [movePipelineCandidate]);

  return (
    <div style={{ display: 'flex', height: '100%', background: 'var(--bg-secondary)', position: 'relative', overflow: 'hidden' }}>
      <Sidebar active={active} onNav={onNav} />
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
        <Topbar title={title}
          onSearch={() => setSearchOpen(true)}
          onSettings={() => setSettingsOpen(true)} />
        <div style={{ flex: 1, overflow: 'auto' }}>
          <div style={{ maxWidth: 1280, margin: '0 auto', padding: '24px 32px 40px' }}>
            {typeof children === 'function'
              ? children({ openCandidate })
              : children}
          </div>
        </div>
      </div>
      <AISearchModal open={searchOpen} onClose={() => setSearchOpen(false)} onOpenCandidate={openCandidate} />
      <SettingsModal open={settingsOpen} onClose={() => setSettingsOpen(false)} />
      {PD && oppId ? (
        <PD oppId={oppId} onClose={closeCandidate} onMove={movePipelineCandidate} onReject={rejectPipelineCandidate} />
      ) : (
        <CandidateDrawer candidate={candidate} onClose={closeCandidate} />
      )}
    </div>
  );
}

/* ─────────────── INBOX ─────────────── */

function InboxPage({ onNav }) {
  const [filter, setFilter] = React.useState('all');

  const FILTERS = [
    { id: 'all',        label: 'All',           match: () => true },
    { id: 'offers',     label: 'Offers',        match: (u) => u.t.startsWith('offer') },
    { id: 'interviews', label: 'Interviews',    match: (u) => u.t === 'interview' },
    { id: 'stage',      label: 'Stage changes', match: (u) => u.t === 'stage' },
  ];

  /* repeat UPDATES a few times to simulate a longer inbox */
  const allItems = [
    ...UPDATES,
    { t: 'offer-sent',    who: 'Aaron Lee',        what: 'offer sent · Operations Lead, CS',         when: '2d',  tone: 'brand' },
    { t: 'stage',         who: 'Valentina Cruz',   what: 'moved to Screening · Product Designer',    when: '2d',  tone: 'neutral' },
    { t: 'offer-decline', who: 'Renata Oliveira',  what: 'declined offer · Product Manager, Risk',   when: '3d',  tone: 'dest' },
    { t: 'interview',     who: 'Pooja Iyer',       what: 'interview scheduled · Data Analyst',        when: '3d',  tone: 'brand' },
    { t: 'stage',         who: 'Jonas Weber',      what: 'moved to Applied · Senior Backend',         when: '4d',  tone: 'neutral' },
    { t: 'offer-accept',  who: 'Thiago Almeida',   what: 'accepted offer · Frontend Engineer',        when: '5d',  tone: 'prog' },
  ];

  const visible = allItems.filter(FILTERS.find(f => f.id === filter)?.match || (() => true));

  const ICON_MAP = {
    'offer-accept':  { icon: <I.Check width="16" height="16" />,    tone: 'prog' },
    'offer-sent':    { icon: <I.Send width="16" height="16" />,     tone: 'brand' },
    'offer-decline': { icon: <I.X width="16" height="16" />,        tone: 'dest' },
    'interview':     { icon: <I.Calendar width="16" height="16" />, tone: 'brand' },
    'stage':         { icon: <I.ArrowUp width="16" height="16" />,  tone: 'neutral' },
  };
  const toneColors = {
    brand:   { bg: 'var(--indigo-20)', fg: 'var(--indigo-90)' },
    prog:    { bg: 'var(--green-20)',  fg: 'var(--green-90)' },
    dest:    { bg: 'var(--red-20)',    fg: 'var(--red-90)' },
    neutral: { bg: 'var(--neutral-20)',fg: 'var(--neutral-80)' },
  };

  return (
    <PageShell active="inbox" onNav={onNav} title="Inbox">
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 20, flexWrap: 'wrap', gap: 12 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 26, fontWeight: 600, letterSpacing: '-0.01em' }}>Inbox</h2>
          <div style={{ fontSize: 13, color: 'var(--content-tertiary)', marginTop: 4 }}>{visible.length} notifications</div>
        </div>
        <div style={{ display: 'flex', gap: 6 }}>
          {FILTERS.map(f => (
            <Pill key={f.id}
              tone={filter === f.id ? 'brand' : 'neutral'}
              active={filter === f.id}
              onClick={() => setFilter(f.id)}>
              {f.label}
            </Pill>
          ))}
        </div>
      </div>

      <div style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 16, overflow: 'hidden' }}>
        {visible.length === 0 && (
          <div style={{ padding: 40, textAlign: 'center', color: 'var(--content-tertiary)', fontSize: 14 }}>
            Nothing here yet.
          </div>
        )}
        {visible.map((u, i) => {
          const ic = ICON_MAP[u.t] || ICON_MAP['stage'];
          const tc = toneColors[ic.tone] || toneColors.neutral;
          return (
            <div key={i} style={{
              display: 'grid', gridTemplateColumns: 'auto 1fr auto', gap: 16,
              padding: '16px 20px', alignItems: 'center',
              borderBottom: i < visible.length - 1 ? '1px solid var(--stroke-secondary)' : 'none',
              transition: 'background 120ms',
            }}
            onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-secondary)'}
            onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
              <div style={{ width: 36, height: 36, borderRadius: 10, background: tc.bg, color: tc.fg,
                display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                {ic.icon}
              </div>
              <div>
                <div style={{ fontSize: 14 }}>
                  <span style={{ fontWeight: 600 }}>{u.who}</span>
                  <span style={{ color: 'var(--content-secondary)', marginLeft: 8 }}>{u.what}</span>
                </div>
              </div>
              <div style={{ fontSize: 12, color: 'var(--content-tertiary)', whiteSpace: 'nowrap' }}>{u.when} ago</div>
            </div>
          );
        })}
      </div>
    </PageShell>
  );
}

/* ─────────────── CANDIDATES ─────────────── */

function CandidatesPage({ onNav }) {
  const [search, setSearch] = React.useState('');
  const [stageFilter, setStageFilter] = React.useState('all');
  const [reqFilter, setReqFilter] = React.useState('all');
  const [sort, setSort] = React.useState('score');

  const stages = ['all', ...Array.from(new Set(CANDIDATES.map(c => c.stage)))];
  const reqOptions = [
    { value: 'all', label: 'All jobs' },
    ...REQS.map(r => ({ value: r.id, label: r.title })),
  ];

  const filtered = React.useMemo(() => {
    let list = [...CANDIDATES];
    if (search.trim()) {
      const q = search.toLowerCase();
      list = list.filter(c =>
        c.name.toLowerCase().includes(q) ||
        (c.roleLabel || roleLabel(c.role)).toLowerCase().includes(q) ||
        c.loc.toLowerCase().includes(q) ||
        c.stage.toLowerCase().includes(q)
      );
    }
    if (stageFilter !== 'all') list = list.filter(c => c.stage === stageFilter);
    if (reqFilter !== 'all') {
      const role = reqById(reqFilter)?.role;
      list = list.filter(c => c.role === role);
    }
    if (sort === 'score')  list.sort((a, b) => b.score - a.score);
    if (sort === 'name')   list.sort((a, b) => a.name.localeCompare(b.name));
    if (sort === 'recent') list.sort((a, b) => parseFloat(a.lastTouch) - parseFloat(b.lastTouch));
    return list;
  }, [search, stageFilter, reqFilter, sort]);

  const STAGE_TONE = {
    'Applied':   'neutral', 'Screening': 'brand', 'Interview': 'brand',
    'Take-home': 'warn',    'Offer':     'prog',  'Hired':     'prog',
  };

  return (
    <PageShell active="candidates" onNav={onNav} title="Candidates">
      {({ openCandidate }) => (
        <>
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 20, flexWrap: 'wrap', gap: 12 }}>
            <div>
              <h2 style={{ margin: 0, fontSize: 26, fontWeight: 600, letterSpacing: '-0.01em' }}>Candidates</h2>
              <div style={{ fontSize: 13, color: 'var(--content-tertiary)', marginTop: 4 }}>
                {filtered.length} of {CANDIDATES.length} candidates
              </div>
            </div>
          </div>

          {/* filters row */}
          <div style={{ display: 'flex', gap: 10, marginBottom: 16, flexWrap: 'wrap', alignItems: 'center' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px',
              background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 10, flex: '1 1 200px', minWidth: 0 }}>
              <I.Search width="14" height="14" style={{ color: 'var(--content-tertiary)', flexShrink: 0 }} />
              <input
                placeholder="Search by name, role, location…"
                value={search} onChange={(e) => setSearch(e.target.value)}
                style={{ border: 0, outline: 0, background: 'transparent', flex: 1, minWidth: 0,
                  fontSize: 13, fontFamily: 'var(--font-sans)', color: 'var(--content-primary)' }} />
              {search && (
                <button onClick={() => setSearch('')} style={{ border: 0, background: 'transparent', cursor: 'pointer', color: 'var(--content-tertiary)', padding: 0, lineHeight: 1 }}>
                  <I.X width="14" height="14" />
                </button>
              )}
            </div>
            <Select value={stageFilter} onChange={setStageFilter} width={160}
              options={stages.map(s => ({ value: s, label: s === 'all' ? 'All stages' : s }))} />
            <Select value={reqFilter} onChange={setReqFilter} width={220}
              options={reqOptions} icon={<I.Briefcase width="14" height="14" />} />
            <Select value={sort} onChange={setSort} width={160}
              options={[
                { value: 'score',  label: 'AI score' },
                { value: 'name',   label: 'Name A–Z' },
                { value: 'recent', label: 'Most recent' },
              ]} />
          </div>

          {/* table */}
          <div style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 16, overflow: 'hidden' }}>
            {/* header */}
            <div style={{ display: 'grid', gridTemplateColumns: '2fr 1.2fr 1fr 1fr 1fr auto',
              gap: 0, background: 'var(--bg-secondary)', borderBottom: '1px solid var(--stroke-secondary)',
              fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)',
              textTransform: 'uppercase', letterSpacing: '.06em' }}>
              {['Candidate', 'Role', 'Location', 'Stage', 'Last touch', 'Score'].map((h, i) => (
                <div key={h} style={{ padding: '12px 16px', borderLeft: i > 0 ? '1px solid var(--stroke-secondary)' : 'none' }}>{h}</div>
              ))}
            </div>
            {filtered.length === 0 && (
              <div style={{ padding: 40, textAlign: 'center', color: 'var(--content-tertiary)', fontSize: 14 }}>
                No candidates match your filters.
              </div>
            )}
            {filtered.map((c, i) => (
              <div key={c.id}
                onClick={() => openCandidate(c)}
                style={{ display: 'grid', gridTemplateColumns: '2fr 1.2fr 1fr 1fr 1fr auto', gap: 0,
                  borderBottom: i < filtered.length - 1 ? '1px solid var(--stroke-secondary)' : 'none',
                  cursor: 'pointer', transition: 'background 120ms' }}
                onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-secondary)'}
                onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
                <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', gap: 10 }}>
                  <Avatar name={c.name} size={32} tone="auto" />
                  <div>
                    <div style={{ fontWeight: 600, fontSize: 14 }}>{c.name}</div>
                    <div style={{ fontSize: 11, color: 'var(--content-tertiary)' }}>{c.langs.join(' · ')}</div>
                  </div>
                </div>
                <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)' }}>
                  {c.roleLabel || roleLabel(c.role)}
                </div>
                <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontSize: 13, color: 'var(--content-secondary)', borderLeft: '1px solid var(--stroke-secondary)' }}>
                  {c.loc}
                </div>
                <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', borderLeft: '1px solid var(--stroke-secondary)' }}>
                  <Pill tone={STAGE_TONE[c.stage] || 'neutral'} dot>{c.stage}</Pill>
                </div>
                <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontSize: 13, color: 'var(--content-tertiary)', borderLeft: '1px solid var(--stroke-secondary)' }}>
                  {c.lastTouch}
                </div>
                <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', borderLeft: '1px solid var(--stroke-secondary)' }}>
                  <ScoreRing score={c.score} size={38} stroke={3} />
                </div>
              </div>
            ))}
          </div>
        </>
      )}
    </PageShell>
  );
}

/* ─────────────── REQUISITIONS ─────────────── */

function RequisitionDrawer({ reqSummary, onClose, onDeleted }) {
  const [detail, setDetail] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [deleting, setDeleting] = React.useState(false);

  React.useEffect(() => {
    if (!reqSummary) return;
    setLoading(true);
    setDetail(null);
    fetch(`/api/postings/${reqSummary.id}`)
      .then(r => r.ok ? r.json() : null)
      .then(d => setDetail(d))
      .catch(() => {})
      .finally(() => setLoading(false));
  }, [reqSummary]);

  const handleDelete = () => {
    if (!reqSummary) return;
    if (!confirm('Are you sure?')) return;
    setDeleting(true);
    fetch(`/api/postings/${reqSummary.id}`, { method: 'DELETE' })
      .then(r => r.ok ? r.json() : Promise.reject(new Error(`HTTP ${r.status}`)))
      .then(() => { onDeleted && onDeleted(reqSummary.id); onClose(); })
      .catch(err => { console.error('[ATS] delete posting failed', err); alert('Delete failed — see console.'); })
      .finally(() => setDeleting(false));
  };

  if (!reqSummary) return null;

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 50, background: 'rgba(5,5,5,0.4)' }}>
      <div onClick={(e) => e.stopPropagation()} style={{
        position: 'absolute', right: 0, top: 0, bottom: 0, width: 540,
        background: 'var(--bg-primary)', boxShadow: 'var(--shadow-lg)',
        display: 'flex', flexDirection: 'column'
      }}>
        {/* header */}
        <div style={{ padding: 20, display: 'flex', alignItems: 'flex-start', gap: 12, borderBottom: '1px solid var(--stroke-secondary)' }}>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em' }}>
              Job
            </div>
            <div style={{ fontWeight: 600, fontSize: 18, marginTop: 4 }}>{reqSummary.title}</div>
            <div style={{ fontSize: 13, color: 'var(--content-tertiary)', marginTop: 4 }}>
              {reqSummary.dept} · {reqSummary.loc} · Owner: {reqSummary.owner}
            </div>
          </div>
          <button
            className="icon-btn"
            onClick={() => {
              const url = `${window.location.origin}/#reqs/${reqSummary.id}`;
              navigator.clipboard.writeText(url).then(
                () => { const t = document.getElementById('req-copied'); if (t) { t.style.opacity = '1'; setTimeout(() => { t.style.opacity = '0'; }, 1600); } },
                () => alert(url),
              );
            }}
            title="Copy shareable link"
          >
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" />
              <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" />
            </svg>
          </button>
          <span id="req-copied" style={{ fontSize: 11, color: 'var(--green-70)', opacity: 0, transition: 'opacity 150ms', alignSelf: 'center' }}>Copied</span>
          <button className="icon-btn" onClick={onClose}><I.X width="18" height="18" /></button>
        </div>

        {/* body */}
        <div style={{ overflow: 'auto', padding: 20, display: 'flex', flexDirection: 'column', gap: 18, flex: 1 }}>
          {/* stats */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 10 }}>
            <Stat label="Applicants" value={reqSummary.applicants} />
            <Stat label="Hires"      value={reqSummary.hires} />
            <Stat label="Days open"  value={`${reqSummary.days}d`} />
            <Stat label="AI fill est." value={`~${reqSummary.predicted}d`} />
          </div>

          <div>
            <Pill tone={reqSummary.status === 'On track' ? 'prog' : 'warn'} dot>{reqSummary.status}</Pill>
          </div>

          {loading && <div style={{ fontSize: 13, color: 'var(--content-tertiary)' }}>Loading details…</div>}

          {detail && (
            <>
              {detail.overview && (
                <div>
                  <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 6 }}>Overview</div>
                  <div style={{ fontSize: 13, lineHeight: 1.5, whiteSpace: 'pre-wrap' }}>{detail.overview}</div>
                </div>
              )}
              {detail.responsibilities && detail.responsibilities.length > 0 && (
                <div>
                  <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 6 }}>Responsibilities</div>
                  <ul style={{ margin: 0, paddingLeft: 18, fontSize: 13, lineHeight: 1.5 }}>
                    {detail.responsibilities.map((r, i) => <li key={i}>{r}</li>)}
                  </ul>
                </div>
              )}
              {detail.requirements && detail.requirements.length > 0 && (
                <div>
                  <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 6 }}>Requirements</div>
                  <ul style={{ margin: 0, paddingLeft: 18, fontSize: 13, lineHeight: 1.5 }}>
                    {detail.requirements.map((r, i) => <li key={i}>{r}</li>)}
                  </ul>
                </div>
              )}
              {detail.niceToHaves && detail.niceToHaves.length > 0 && (
                <div>
                  <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 6 }}>Nice-to-haves</div>
                  <ul style={{ margin: 0, paddingLeft: 18, fontSize: 13, lineHeight: 1.5 }}>
                    {detail.niceToHaves.map((r, i) => <li key={i}>{r}</li>)}
                  </ul>
                </div>
              )}
              {detail.criteria && detail.criteria.length > 0 && (
                <div>
                  <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 6 }}>AI scoring criteria</div>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                    {detail.criteria.map(c => (
                      <div key={c.id} style={{ fontSize: 12, padding: '6px 10px', borderRadius: 8, background: 'var(--bg-secondary)' }}>
                        <span style={{ fontWeight: 600 }}>{c.label}</span>
                        <span style={{ color: 'var(--content-tertiary)', marginLeft: 6 }}>· weight {c.weight}</span>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </>
          )}
        </div>

        {/* footer */}
        <div style={{ padding: 16, borderTop: '1px solid var(--stroke-secondary)', display: 'flex', justifyContent: 'flex-end' }}>
          <button
            className="btn"
            style={{
              background: 'var(--action-destructive)',
              color: 'var(--action-text, white)',
              borderColor: 'var(--action-destructive)',
            }}
            onClick={handleDelete}
            disabled={deleting}
          >
            <I.X width="14" height="14" />
            {deleting ? 'Deleting…' : 'Delete job'}
          </button>
        </div>
      </div>
    </div>
  );
}

function RequisitionsPage({ onNav }) {
  const { role } = React.useContext(RoleContext);
  const [statusFilter, setStatusFilter] = React.useState('all');
  const [search, setSearch] = React.useState('');
  const [newPostingOpen, setNewPostingOpen] = React.useState(false);
  const [activeReq, setActiveReq] = React.useState(null);
  const NewPostingModal = window.NewPostingModal;

  const openReq = React.useCallback((r) => {
    setActiveReq(r);
    _setHashId('reqs', r?.id || null);
  }, []);
  const closeReq = React.useCallback(() => {
    setActiveReq(null);
    _setHashId('reqs', null);
  }, []);

  // Sync drawer with URL hash for shareable links.
  React.useEffect(() => {
    const sync = () => {
      const { view, id } = _parseHash();
      if (view !== 'reqs') return;
      if (id) {
        const r = (window.REQS || []).find(x => x.id === id);
        if (r && (!activeReq || activeReq.id !== id)) setActiveReq(r);
      } else if (activeReq) {
        setActiveReq(null);
      }
    };
    sync();
    window.addEventListener('hashchange', sync);
    return () => window.removeEventListener('hashchange', sync);
  }, [activeReq]);

  const base = role === 'manager' ? REQS.filter(r => r.owner === 'Carla R.') : REQS;
  const visible = base.filter(r => {
    if (statusFilter === 'at-risk' && r.status !== 'At risk') return false;
    if (statusFilter === 'on-track' && r.status !== 'On track') return false;
    if (search.trim() && !r.title.toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  const atRisk  = base.filter(r => r.status === 'At risk').length;
  const onTrack = base.filter(r => r.status === 'On track').length;

  return (
    <PageShell active="reqs" onNav={onNav} title="Jobs">
      {({ openCandidate }) => (
        <>
          <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 20, flexWrap: 'wrap', gap: 12 }}>
            <div>
              <h2 style={{ margin: 0, fontSize: 26, fontWeight: 600, letterSpacing: '-0.01em' }}>Jobs</h2>
              <div style={{ fontSize: 13, color: 'var(--content-tertiary)', marginTop: 4 }}>
                {onTrack} on track · {atRisk} at risk
              </div>
            </div>
            <button
              className="btn btn-brand"
              style={{ fontSize: 13 }}
              onClick={() => setNewPostingOpen(true)}
              disabled={!NewPostingModal}
              title={!NewPostingModal ? 'Loading…' : 'Open new job form'}
            >
              <I.Plus width="14" height="14" /> New job
            </button>
          </div>

          {/* summary cards */}
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 24 }}>
            {[
              { label: 'Open reqs',        value: base.length,                           tone: 'neutral' },
              { label: 'At risk',          value: atRisk,                                tone: atRisk > 0 ? 'warn' : 'prog' },
              { label: 'Avg applicants',   value: Math.round(base.reduce((a,r) => a + r.applicants, 0) / base.length), tone: 'neutral' },
            ].map(s => (
              <div key={s.label} style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 14, padding: '16px 20px' }}>
                <div style={{ fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em' }}>{s.label}</div>
                <div style={{ fontSize: 32, fontWeight: 600, marginTop: 6, letterSpacing: '-0.01em',
                  color: s.tone === 'warn' ? 'var(--yellow-70)' : s.tone === 'prog' ? 'var(--green-70)' : 'var(--content-primary)' }}>
                  {s.value}
                </div>
              </div>
            ))}
          </div>

          {/* filter row */}
          <div style={{ display: 'flex', gap: 10, marginBottom: 16, alignItems: 'center', flexWrap: 'wrap' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 8, padding: '8px 12px',
              background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 10, flex: '1 1 200px' }}>
              <I.Search width="14" height="14" style={{ color: 'var(--content-tertiary)' }} />
              <input placeholder="Search jobs…" value={search} onChange={(e) => setSearch(e.target.value)}
                style={{ border: 0, outline: 0, background: 'transparent', flex: 1, fontSize: 13, fontFamily: 'var(--font-sans)', color: 'var(--content-primary)' }} />
            </div>
            {['all', 'on-track', 'at-risk'].map(f => (
              <Pill key={f}
                tone={statusFilter === f ? 'brand' : 'neutral'}
                active={statusFilter === f}
                onClick={() => setStatusFilter(f)}>
                {f === 'all' ? 'All' : f === 'on-track' ? 'On track' : 'At risk'}
              </Pill>
            ))}
          </div>

          <div style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 16, overflow: 'hidden' }}>
            {/* header */}
            <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr 1fr 1fr',
              background: 'var(--bg-secondary)', borderBottom: '1px solid var(--stroke-secondary)',
              fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em' }}>
              {['Role', 'Department', 'Applicants', 'Days open', 'AI fill est.', 'Status'].map((h, i) => (
                <div key={h} style={{ padding: '12px 16px', borderLeft: i > 0 ? '1px solid var(--stroke-secondary)' : 'none' }}>{h}</div>
              ))}
            </div>
            {visible.length === 0 && (
              <div style={{ padding: 40, textAlign: 'center', color: 'var(--content-tertiary)', fontSize: 14 }}>No jobs match.</div>
            )}
            {visible.map((r, i) => {
              const cands = candsForReq(r.id);
              return (
                <div key={r.id} style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr 1fr 1fr',
                  borderBottom: i < visible.length - 1 ? '1px solid var(--stroke-secondary)' : 'none',
                  transition: 'background 120ms', cursor: 'pointer' }}
                  onClick={() => openReq(r)}
                  onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-secondary)'}
                  onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
                  <div style={{ padding: '14px 16px' }}>
                    <div style={{ fontWeight: 600, fontSize: 14 }}>{r.title}</div>
                    <div style={{ fontSize: 12, color: 'var(--content-tertiary)', marginTop: 2 }}>{r.loc} · {r.hires} hired · Owner: {r.owner}</div>
                  </div>
                  <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)' }}>{r.dept}</div>
                  <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontWeight: 600, fontSize: 14, borderLeft: '1px solid var(--stroke-secondary)', fontVariantNumeric: 'tabular-nums' }}>{r.applicants}</div>
                  <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)',
                    color: r.days > r.target ? 'var(--yellow-70)' : 'var(--content-primary)', fontWeight: 600 }}>{r.days}d</div>
                  <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)',
                    color: r.predicted > r.target ? 'var(--yellow-70)' : 'var(--green-70)', fontWeight: 600 }}>~{r.predicted}d</div>
                  <div style={{ padding: '14px 16px', display: 'flex', alignItems: 'center', borderLeft: '1px solid var(--stroke-secondary)' }}>
                    <Pill tone={r.status === 'On track' ? 'prog' : 'warn'} dot>{r.status}</Pill>
                  </div>
                </div>
              );
            })}
          </div>

          {newPostingOpen && NewPostingModal && (
            <NewPostingModal
              onClose={() => setNewPostingOpen(false)}
              onCreated={() => { setNewPostingOpen(false); window.location.reload(); }}
            />
          )}

          {activeReq && (
            <RequisitionDrawer
              reqSummary={activeReq}
              onClose={closeReq}
              onDeleted={() => window.location.reload()}
            />
          )}
        </>
      )}
    </PageShell>
  );
}

/* ─────────────── INTERVIEWS ─────────────── */

function InterviewsPage({ onNav }) {
  const interviewCandidates = CANDIDATES.filter(c => c.stage === 'Interview' || c.stage === 'Take-home');

  const scheduled = [
    { time: '09:00', candidate: CANDIDATES[0], type: 'Technical',      interviewer: 'Carla R.',  link: '#' },
    { time: '11:30', candidate: CANDIDATES[3], type: 'Product review', interviewer: 'Diego F.',  link: '#' },
    { time: '14:00', candidate: CANDIDATES[8], type: 'Culture fit',    interviewer: 'Pablo M.',  link: '#' },
    { time: '15:30', candidate: CANDIDATES[2], type: 'Take-home debrief', interviewer: 'Carla R.', link: '#' },
  ].filter(s => s.candidate);

  const upcoming = [
    { date: 'Tomorrow',   candidate: CANDIDATES[2], type: 'Portfolio review', interviewer: 'Diego F.' },
    { date: 'Wed 28 May', candidate: CANDIDATES[1], type: 'Technical',        interviewer: 'Pablo M.' },
    { date: 'Thu 29 May', candidate: CANDIDATES[3], type: 'Final round',      interviewer: 'Carla R.' },
    { date: 'Fri 30 May', candidate: CANDIDATES[8], type: 'Final round',      interviewer: 'Carla R.' },
  ].filter(u => u.candidate);

  return (
    <PageShell active="interviews" onNav={onNav} title="Interviews">
      {({ openCandidate }) => (
        <>
          <div style={{ marginBottom: 20 }}>
            <h2 style={{ margin: 0, fontSize: 26, fontWeight: 600, letterSpacing: '-0.01em' }}>Interviews</h2>
            <div style={{ fontSize: 13, color: 'var(--content-tertiary)', marginTop: 4 }}>
              {scheduled.length} scheduled today · {upcoming.length} upcoming
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
            {/* Today */}
            <div>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 10 }}>
                Today · Wed 21 May
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {scheduled.map((s, i) => (
                  <div key={i} style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)',
                    borderRadius: 14, padding: '14px 16px', display: 'flex', gap: 14, alignItems: 'center',
                    cursor: 'pointer', transition: 'border-color 120ms' }}
                    onClick={() => openCandidate(s.candidate)}
                    onMouseEnter={(e) => e.currentTarget.style.borderColor = 'var(--stroke-primary)'}
                    onMouseLeave={(e) => e.currentTarget.style.borderColor = 'var(--stroke-secondary)'}>
                    <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--indigo-50)',
                      fontVariantNumeric: 'tabular-nums', minWidth: 44 }}>{s.time}</div>
                    <div style={{ width: 1, height: 36, background: 'var(--stroke-secondary)', flexShrink: 0 }} />
                    <Avatar name={s.candidate.name} size={32} tone="auto" />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 600, fontSize: 14 }}>{s.candidate.name}</div>
                      <div style={{ fontSize: 12, color: 'var(--content-tertiary)' }}>
                        {s.type} · with {s.interviewer}
                      </div>
                    </div>
                    <ScoreRing score={s.candidate.score} size={34} stroke={3} />
                  </div>
                ))}
              </div>
            </div>

            {/* Upcoming */}
            <div>
              <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 10 }}>
                Upcoming
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {upcoming.map((u, i) => (
                  <div key={i} style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)',
                    borderRadius: 14, padding: '14px 16px', display: 'flex', gap: 14, alignItems: 'center',
                    cursor: 'pointer', transition: 'border-color 120ms' }}
                    onClick={() => openCandidate(u.candidate)}
                    onMouseEnter={(e) => e.currentTarget.style.borderColor = 'var(--stroke-primary)'}
                    onMouseLeave={(e) => e.currentTarget.style.borderColor = 'var(--stroke-secondary)'}>
                    <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--content-tertiary)',
                      minWidth: 72, whiteSpace: 'nowrap' }}>{u.date}</div>
                    <div style={{ width: 1, height: 36, background: 'var(--stroke-secondary)', flexShrink: 0 }} />
                    <Avatar name={u.candidate.name} size={32} tone="auto" />
                    <div style={{ flex: 1, minWidth: 0 }}>
                      <div style={{ fontWeight: 600, fontSize: 14 }}>{u.candidate.name}</div>
                      <div style={{ fontSize: 12, color: 'var(--content-tertiary)' }}>
                        {u.type} · with {u.interviewer}
                      </div>
                    </div>
                    <ScoreRing score={u.candidate.score} size={34} stroke={3} />
                  </div>
                ))}
              </div>
            </div>
          </div>

          {/* Candidates in interview/take-home */}
          <div style={{ marginTop: 28 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 12 }}>
              In-process candidates ({interviewCandidates.length})
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 10 }}>
              {interviewCandidates.map(c => (
                <div key={c.id} onClick={() => openCandidate(c)} style={{
                  background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)',
                  borderRadius: 14, padding: '14px 16px', display: 'flex', gap: 12, alignItems: 'center',
                  cursor: 'pointer', transition: 'border-color 120ms' }}
                  onMouseEnter={(e) => e.currentTarget.style.borderColor = 'var(--stroke-primary)'}
                  onMouseLeave={(e) => e.currentTarget.style.borderColor = 'var(--stroke-secondary)'}>
                  <ScoreRing score={c.score} size={40} stroke={3} />
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight: 600, fontSize: 14 }}>{c.name}</div>
                    <div style={{ fontSize: 12, color: 'var(--content-tertiary)' }}>{c.roleLabel || roleLabel(c.role)} · {c.loc}</div>
                  </div>
                  <Pill tone={c.stage === 'Take-home' ? 'warn' : 'brand'} dot>{c.stage}</Pill>
                </div>
              ))}
            </div>
          </div>
        </>
      )}
    </PageShell>
  );
}

/* ─────────────── REPORTS ─────────────── */

function ReportsPage({ onNav }) {
  const [period, setPeriod] = React.useState('month');
  const periodObj = TIME_PERIODS.find(p => p.id === period);

  const kpiDefs = [
    { id: 'ttf',    label: 'Time to fill',       fmt: (v) => `${Math.round(v)}d`,   target: 30, lowerBetter: true },
    { id: 'tth',    label: 'Time to hire',       fmt: (v) => `${v.toFixed(1)}d`,    target: 7,  lowerBetter: true },
    { id: 'offer',  label: 'Offer acceptance',   fmt: (v) => `${Math.round(v)}%`,   target: 90, lowerBetter: false },
    { id: 'screen', label: 'Screening approval', fmt: (v) => `${Math.round(v)}%`,   target: 60, lowerBetter: false },
    { id: 'attr',   label: 'Attrition',          fmt: (v) => `${v.toFixed(1)}%`,    target: 5,  lowerBetter: true },
    { id: 'applied',label: 'Applicants',         fmt: (v) => `${Math.round(v)}`,    target: 40, lowerBetter: false },
  ];

  const kpis = kpiDefs.map(k => {
    const s = metricSeries(k.id, period, 'all');
    const onTrack = k.lowerBetter ? s.current <= k.target : s.current >= k.target;
    return { ...k, ...s, tone: onTrack ? 'prog' : 'warn', display: k.fmt(s.current) };
  });

  return (
    <PageShell active="reports" onNav={onNav} title="Reports">
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 20, flexWrap: 'wrap', gap: 12 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 26, fontWeight: 600, letterSpacing: '-0.01em' }}>Reports</h2>
          <div style={{ fontSize: 13, color: 'var(--content-tertiary)', marginTop: 4 }}>
            Hiring KPIs · all jobs
          </div>
        </div>
        <Select value={period} onChange={setPeriod} width={160}
          options={TIME_PERIODS.map(p => ({ value: p.id, label: p.label }))}
          icon={<I.Calendar width="14" height="14" />} />
      </div>

      {/* KPI grid */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 28 }}>
        {kpis.map(k => (
          <div key={k.id} style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 16, padding: 20 }}>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10 }}>
              <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--content-tertiary)' }}>{k.label}</div>
              <Pill tone={k.tone}>
                {k.trendPct > 0 ? <I.ArrowUp width="10" height="10" /> : k.trendPct < 0 ? <I.ArrowDn width="10" height="10" /> : null}
                {Math.abs(k.trendPct)}%
              </Pill>
            </div>
            <div style={{ fontWeight: 600, fontSize: 28, letterSpacing: '-0.01em', marginBottom: 2 }}>{k.display}</div>
            <div style={{ fontSize: 12, color: 'var(--content-tertiary)', marginBottom: 12 }}>
              Target {k.fmt(k.target)}
            </div>
            <Sparkbar values={k.values} height={36}
              color={k.tone === 'prog' ? 'var(--green-50)' : k.tone === 'warn' ? 'var(--yellow-50)' : 'var(--indigo-30)'} />
            <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 6,
              fontSize: 10, color: 'var(--content-tertiary)' }}>
              <span>{periodObj.binLabel(0)}</span>
              <span>{periodObj.binLabel(k.bins - 1)}</span>
            </div>
          </div>
        ))}
      </div>

      {/* per-req breakdown */}
      <div style={{ background: 'var(--bg-primary)', border: '1px solid var(--stroke-secondary)', borderRadius: 16, overflow: 'hidden' }}>
        <div style={{ padding: '18px 20px', borderBottom: '1px solid var(--stroke-secondary)', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <h3 style={{ margin: 0, fontSize: 16, fontWeight: 600 }}>Breakdown by requisition</h3>
          <span style={{ fontSize: 12, color: 'var(--content-tertiary)' }}>{periodObj.label}</span>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr 1fr',
          background: 'var(--bg-secondary)', borderBottom: '1px solid var(--stroke-secondary)',
          fontSize: 11, fontWeight: 600, color: 'var(--content-tertiary)', textTransform: 'uppercase', letterSpacing: '.06em' }}>
          {['Requisition', 'Applicants', 'Time to fill', 'Time to hire', 'Status'].map((h, i) => (
            <div key={h} style={{ padding: '10px 16px', borderLeft: i > 0 ? '1px solid var(--stroke-secondary)' : 'none' }}>{h}</div>
          ))}
        </div>
        {REQS.map((r, i) => {
          const ttf = metricSeries('ttf', period, r.id);
          const tth = metricSeries('tth', period, r.id);
          return (
            <div key={r.id} style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr 1fr 1fr',
              borderBottom: i < REQS.length - 1 ? '1px solid var(--stroke-secondary)' : 'none',
              transition: 'background 120ms', cursor: 'default' }}
              onMouseEnter={(e) => e.currentTarget.style.background = 'var(--bg-secondary)'}
              onMouseLeave={(e) => e.currentTarget.style.background = 'transparent'}>
              <div style={{ padding: '12px 16px' }}>
                <div style={{ fontWeight: 600, fontSize: 13 }}>{r.title}</div>
                <div style={{ fontSize: 11, color: 'var(--content-tertiary)' }}>{r.dept} · {r.owner}</div>
              </div>
              <div style={{ padding: '12px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)', fontVariantNumeric: 'tabular-nums', fontWeight: 600 }}>{r.applicants}</div>
              <div style={{ padding: '12px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)',
                color: ttf.current > ttf.target ? 'var(--yellow-70)' : 'var(--green-70)', fontWeight: 600 }}>{Math.round(ttf.current)}d</div>
              <div style={{ padding: '12px 16px', display: 'flex', alignItems: 'center', fontSize: 13, borderLeft: '1px solid var(--stroke-secondary)',
                color: tth.current > tth.target ? 'var(--yellow-70)' : 'var(--green-70)', fontWeight: 600 }}>{tth.current.toFixed(1)}d</div>
              <div style={{ padding: '12px 16px', display: 'flex', alignItems: 'center', borderLeft: '1px solid var(--stroke-secondary)' }}>
                <Pill tone={r.status === 'On track' ? 'prog' : 'warn'} dot>{r.status}</Pill>
              </div>
            </div>
          );
        })}
      </div>
    </PageShell>
  );
}

window.InboxPage        = InboxPage;
window.CandidatesPage   = CandidatesPage;
window.RequisitionsPage = RequisitionsPage;
window.InterviewsPage   = InterviewsPage;
window.ReportsPage      = ReportsPage;
