/* ════════════════════════════════════════════════════════════
   Apple-grade interactive primitives:
   P3-2 Snackbar / Toast    window.toast()
   P3-3 Modal Sheet         <AppleSheet>
   P4-1 Command Palette     ⌘K        <CommandPalette>
   ════════════════════════════════════════════════════════════ */

const { useState: prim_s, useEffect: prim_e, useRef: prim_r, useMemo: prim_m } = React;

/* ─── P3-2 · Snackbar / Toast ──────────────────────────────── */
window.__toasts = [];
window.__toastSub = new Set();
window.toast = function (opts) {
  if (typeof opts === 'string') opts = { msg: opts };
  const id = Math.random().toString(36).slice(2);
  const item = { id, ttl: 4000, kind: 'info', ...opts };
  window.__toasts.push(item);
  window.__toastSub.forEach(fn => fn());
  setTimeout(() => {
    window.__toasts = window.__toasts.filter(t => t.id !== id);
    window.__toastSub.forEach(fn => fn());
  }, item.ttl);
  window.haptic?.[item.kind === 'success' ? 'success' : item.kind === 'error' ? 'error' : 'light']?.();
  return id;
};

function ToastHost() {
  const [, force] = prim_s(0);
  prim_e(() => {
    const fn = () => force(n => n + 1);
    window.__toastSub.add(fn);
    return () => window.__toastSub.delete(fn);
  }, []);
  const items = window.__toasts;
  if (!items.length) return null;
  return (
    <div className="toast-host">
      {items.map(t => (
        <div key={t.id} className={'toast toast-' + (t.kind || 'info')}>
          <span className="toast-msg">{t.msg}</span>
          {t.action && (
            <button className="toast-action"
                    onClick={() => { t.action.run?.(); window.__toasts = window.__toasts.filter(x => x.id !== t.id); window.__toastSub.forEach(fn => fn()); }}>
              {t.action.label}
            </button>
          )}
        </div>
      ))}
    </div>
  );
}
window.ToastHost = ToastHost;

/* ─── P3-3 · Apple-style modal sheet ───────────────────────── */
function AppleSheet({ open, onClose, title, children, footer }) {
  const [drag, setDrag] = prim_s(0);
  const startY = prim_r(0);
  prim_e(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === 'Escape') onClose?.(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open]);
  if (!open) return null;

  const onPDown = (e) => { startY.current = e.clientY; };
  const onPMove = (e) => {
    if (!startY.current) return;
    const d = Math.max(0, e.clientY - startY.current);
    setDrag(d);
  };
  const onPUp = () => {
    if (drag > 100) { onClose?.(); }
    setDrag(0);
    startY.current = 0;
  };

  return (
    <>
      <div className="sheet-veil" onClick={onClose}/>
      <div className="sheet-card" style={{ transform: `translateY(${drag}px)`, transition: drag === 0 ? 'transform var(--dur-sheet) var(--ease-spring-soft)' : 'none' }}>
        <div className="sheet-handle"
             onPointerDown={onPDown} onPointerMove={onPMove}
             onPointerUp={onPUp} onPointerCancel={onPUp}>
          <span/>
        </div>
        {title && <div className="sheet-title">{title}</div>}
        <div className="sheet-body">{children}</div>
        {footer && <div className="sheet-foot">{footer}</div>}
      </div>
    </>
  );
}
window.AppleSheet = AppleSheet;

/* ─── P4-1 · Command Palette (⌘K) ──────────────────────────── */
function CommandPalette() {
  const [open, setOpen] = prim_s(false);
  const [q, setQ] = prim_s('');
  const [sel, setSel] = prim_s(0);
  const [, force] = prim_s(0);
  const inputRef = prim_r(null);

  prim_e(() => {
    const onKey = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault();
        setOpen(o => !o);
        setQ('');
        setSel(0);
        window.haptic?.medium?.();
      } else if (e.key === 'Escape' && open) {
        setOpen(false);
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open]);

  prim_e(() => {
    if (!window.commands) return;
    return window.commands.subscribe(() => force(n => n + 1));
  }, []);

  prim_e(() => { if (open) setTimeout(() => inputRef.current?.focus(), 50); }, [open]);

  const cmds = window.commands?.list() || [];
  const lang = window.__LANG || 'zh';
  const filtered = prim_m(() => {
    if (!q) return cmds;
    const lq = q.toLowerCase();
    return cmds.filter(c =>
      (c.label || '').toLowerCase().includes(lq) ||
      (c.en    || '').toLowerCase().includes(lq) ||
      (c.id    || '').toLowerCase().includes(lq)
    );
  }, [q, cmds.length]);

  const grouped = prim_m(() => {
    const g = {};
    filtered.forEach(c => { (g[c.section || 'Actions'] = g[c.section || 'Actions'] || []).push(c); });
    return g;
  }, [filtered]);

  if (!open) return null;

  const flatList = filtered;
  const runSel = (i) => {
    const c = flatList[i];
    if (c) { window.commands.run(c.id); setOpen(false); }
  };
  const onInputKey = (e) => {
    if (e.key === 'ArrowDown') { e.preventDefault(); setSel(s => Math.min(flatList.length - 1, s + 1)); window.haptic?.selection?.(); }
    else if (e.key === 'ArrowUp') { e.preventDefault(); setSel(s => Math.max(0, s - 1)); window.haptic?.selection?.(); }
    else if (e.key === 'Enter') { e.preventDefault(); runSel(sel); }
  };

  let idx = -1;
  return (
    <>
      <div className="cmdk-veil" onClick={() => setOpen(false)}/>
      <div className="cmdk-card" role="dialog" aria-label="Command palette">
        <div className="cmdk-search">
          <span className="cmdk-spy">⌘</span>
          <input ref={inputRef} value={q} onChange={e => { setQ(e.target.value); setSel(0); }}
                 onKeyDown={onInputKey}
                 placeholder={lang === 'zh' ? '搜索命令、跳页、股票…' : 'Type a command or search…'}/>
          <span className="cmdk-esc">esc</span>
        </div>
        <div className="cmdk-list">
          {Object.entries(grouped).map(([sec, arr]) => (
            <div key={sec} className="cmdk-sec">
              <div className="cmdk-sec-h">{sec}</div>
              {arr.map(c => {
                idx++;
                const myIdx = idx;
                const active = myIdx === sel;
                return (
                  <button key={c.id} className={'cmdk-row' + (active ? ' on' : '')}
                          onMouseEnter={() => setSel(myIdx)}
                          onClick={() => runSel(myIdx)}>
                    <span className="cmdk-glyph">{c.glyph || '›'}</span>
                    <span className="cmdk-lab">{lang === 'zh' ? (c.label || c.en) : (c.en || c.label)}</span>
                    {c.shortcut && <span className="cmdk-kbd">{c.shortcut}</span>}
                  </button>
                );
              })}
            </div>
          ))}
          {!flatList.length && (
            <div className="cmdk-empty">{lang === 'zh' ? '没有匹配的命令' : 'No matching commands'}</div>
          )}
        </div>
        <div className="cmdk-foot">
          <span><kbd>↑</kbd><kbd>↓</kbd> {lang==='zh'?'选择':'navigate'}</span>
          <span><kbd>⏎</kbd> {lang==='zh'?'执行':'run'}</span>
          <span><kbd>esc</kbd> {lang==='zh'?'关闭':'close'}</span>
        </div>
      </div>
    </>
  );
}
window.CommandPalette = CommandPalette;
