function useCommands(go, close) {
  return React.useMemo(() => {
    const nav = ROUTES.map(r => ({ id: 'nav-' + r.path, icon: 'CornerDownLeft', group: 'Go to', label: r.label, hint: r.path, run: () => go(r.path) }));
    const proj = PROJECTS.map(p => ({ id: 'p-' + p.title, icon: 'Code2', group: 'Projects', label: p.title, hint: p.category, run: () => { go('/projects'); window.dispatchEvent(new CustomEvent('pf:open-project', { detail: p.title })); } }));
    const acts = [
      { id: 'a-mail', icon: 'Mail', group: 'Actions', label: 'Copy email address', hint: PROFILE.email, run: () => navigator.clipboard && navigator.clipboard.writeText(PROFILE.email) },
      { id: 'a-cv', icon: 'Download', group: 'Actions', label: 'Download résumé', hint: 'PDF', run: () => window.open(PROFILE.resumeUrl, '_blank') },
      { id: 'a-top', icon: 'ArrowUp', group: 'Actions', label: 'Back to top', hint: '', run: () => window.scrollTo({ top: 0, behavior: reduced() ? 'auto' : 'smooth' }) },
      ...PROFILE.socials.map(s => ({ id: 's-' + s.label, icon: s.icon, group: 'Elsewhere', label: s.label, hint: 'Open profile', run: () => window.open(s.href, '_blank') }))
    ];
    return [...nav, ...proj, ...acts];
  }, [go, close]);
}

function CommandPalette({ open, setOpen, go }) {
  const [q, setQ] = React.useState('');
  const [sel, setSel] = React.useState(0);
  const inputRef = React.useRef(null);
  const all = useCommands(go, () => setOpen(false));
  const list = React.useMemo(() => {
    const t = q.trim().toLowerCase();
    if (!t) return all;
    return all.filter(c => (c.label + ' ' + c.group + ' ' + c.hint).toLowerCase().includes(t));
  }, [q, all]);

  React.useEffect(() => { setSel(0); }, [q]);
  React.useEffect(() => {
    if (open) { setQ(''); setTimeout(() => inputRef.current && inputRef.current.focus(), 20); document.body.style.overflow = 'hidden'; }
    else document.body.style.overflow = '';
  }, [open]);

  React.useEffect(() => {
    const onKey = e => {
      const mod = e.metaKey || e.ctrlKey;
      if (mod && e.key.toLowerCase() === 'k') { e.preventDefault(); setOpen(o => !o); return; }
      if (!open) return;
      if (e.key === 'Escape') { e.preventDefault(); setOpen(false); }
      if (e.key === 'ArrowDown') { e.preventDefault(); setSel(s => (s + 1) % Math.max(1, list.length)); }
      if (e.key === 'ArrowUp') { e.preventDefault(); setSel(s => (s - 1 + list.length) % Math.max(1, list.length)); }
      if (e.key === 'Enter' && list[sel]) { e.preventDefault(); list[sel].run(); setOpen(false); }
    };
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [open, list, sel, setOpen]);

  if (!open) return null;
  let lastGroup = null;
  return (
    <div className="pf-cmd" onClick={() => setOpen(false)} role="dialog" aria-modal="true" aria-label="Command palette">
      <div className="pf-cmd-panel" onClick={e => e.stopPropagation()}>
        <div style={{ height: 4, background: 'var(--gradient-sunset-stripe)' }} />
        <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-sm)', padding: 'var(--space-md)', borderBottom: '1px solid var(--hairline-soft)' }}>
          <span style={{ color: 'var(--primary)' }}><Icon name="Search" size={17} /></span>
          <input ref={inputRef} value={q} onChange={e => setQ(e.target.value)} placeholder="Jump to a page, project or action…" aria-label="Search commands"
            style={{ flex: 1, border: 0, outline: 'none', background: 'none', font: 'var(--type-body-md)', color: 'var(--ink)' }} />
          <Kbd>esc</Kbd>
        </div>
        <div role="listbox" aria-label="Commands" style={{ maxHeight: '46vh', overflowY: 'auto', padding: '6px 0' }}>
          {list.length === 0 && <div style={{ padding: 'var(--space-lg) var(--space-md)', font: 'var(--type-body-sm)', color: 'var(--steel)' }}>Nothing matches "{q}".</div>}
          {list.map((c, i) => {
            const head = c.group !== lastGroup ? (lastGroup = c.group) : null;
            return (
              <React.Fragment key={c.id}>
                {head && <div style={{ font: 'var(--type-micro-uppercase)', letterSpacing: 'var(--tracking-eyebrow)', textTransform: 'uppercase', color: 'var(--stone)', padding: '10px var(--space-md) 4px' }}>{head}</div>}
                <button className="pf-cmd-row" role="option" aria-selected={i === sel} onMouseEnter={() => setSel(i)} onClick={() => { c.run(); setOpen(false); }}>
                  <span style={{ color: i === sel ? 'var(--primary)' : 'var(--stone)', display: 'inline-flex' }}><Icon name={c.icon} size={16} /></span>
                  <span style={{ flex: 1 }}>{c.label}</span>
                  {c.hint && <span style={{ font: 'var(--type-caption)', color: 'var(--stone)', fontFamily: 'var(--font-mono)' }}>{c.hint}</span>}
                </button>
              </React.Fragment>
            );
          })}
        </div>
        <div style={{ display: 'flex', gap: 'var(--space-md)', alignItems: 'center', padding: 'var(--space-xs) var(--space-md)', borderTop: '1px solid var(--hairline-soft)', font: 'var(--type-caption)', color: 'var(--steel)' }}>
          <span style={{ display: 'flex', gap: 6, alignItems: 'center' }}><Kbd>↑</Kbd><Kbd>↓</Kbd> navigate</span>
          <span style={{ display: 'flex', gap: 6, alignItems: 'center' }}><Kbd>↵</Kbd> open</span>
          <span style={{ marginLeft: 'auto', fontFamily: 'var(--font-mono)' }}>{list.length} results</span>
        </div>
      </div>
    </div>
  );
}

function ScrollProgress() {
  const [p, setP] = React.useState(0);
  React.useEffect(() => {
    let raf = 0;
    const on = () => {
      if (raf) return;
      raf = requestAnimationFrame(() => {
        raf = 0;
        const max = document.documentElement.scrollHeight - window.innerHeight;
        setP(max > 0 ? Math.min(1, window.scrollY / max) : 0);
      });
    };
    window.addEventListener('scroll', on, { passive: true });
    window.addEventListener('resize', on);
    on();
    return () => { window.removeEventListener('scroll', on); window.removeEventListener('resize', on); };
  }, []);
  return <div className="pf-progress" aria-hidden="true" style={{ width: '100%', transform: 'scaleX(' + p + ')' }} />;
}

Object.assign(window, { CommandPalette, ScrollProgress });
