// tc-preview.jsx — Saved timecards list.
function SavedList({ cards, activeId, onOpen, onDelete }) {
  return (
    <div className="saved">
      <div className="saved-head">
        <span className="rail-label">Saved time cards</span>
        {cards.length > 0 && <span className="rail-count mono">{cards.length}</span>}
      </div>
      {cards.length === 0 && <p className="muted sm pad">No saved cards yet.</p>}
      <ul className="saved-list">
        {cards.map(c => (
          <li key={c.id} className={'saved-item' + (c.id === activeId ? ' on' : '')} onClick={() => onOpen(c.id)}>
            <div className="si-main">
              <div className="si-title">{c.projectTitle || 'Untitled'}</div>
              <div className="si-sub mono">W/E {c.weekEndingStr || '—'}</div>
            </div>
            <button className="si-del" title="Delete" onClick={(e) => { e.stopPropagation(); onDelete(c.id); }}>✕</button>
          </li>
        ))}
      </ul>
    </div>
  );
}

Object.assign(window, { SavedList });

// How many quick-access cards the bottom dock shows before collapsing the rest
// into a "+N more" chip that opens the Saved menu.
const DOCK_MAX = 12;

// ── Library: relocates "saved + new" out of a fat sidebar ────────────────────
// LibraryDock — horizontal strip for the dead space below the form (side layout).
// Shows the most-recent DOCK_MAX items; overflow → "+N more" chip → onMore().
function LibraryDock({ label, items, activeId, onOpen, onDelete, onNew, onMore }) {
  const shown = items.slice(0, DOCK_MAX);
  const overflow = items.length - shown.length;
  return (
    <div className="library-dock">
      <div className="dock-head">
        <span className="dock-label">{label}</span>
        <button className="dock-new" onClick={onNew}>+ New</button>
      </div>
      {items.length === 0 && <div className="dock-empty">{`No saved ${label.toLowerCase()} yet.`}</div>}
      {shown.map(it => (
        <div key={it.id} className={'dock-card' + (it.id === activeId ? ' on' : '')} onClick={() => onOpen(it.id)}>
          <span className="dc-title">{it.title}</span>
          <span className="dc-sub mono">{it.sub}</span>
          <button className="dock-del" title="Delete" onClick={(e) => { e.stopPropagation(); onDelete(it.id); }}>✕</button>
        </div>
      ))}
      {overflow > 0 && (
        <button className="dock-more" onClick={onMore} title="See all in Saved">
          <span className="dm-n">+{overflow}</span>
          <span className="dm-l">more in Saved</span>
        </button>
      )}
    </div>
  );
}

// LibraryMenu — compact top-bar dropdown. Full searchable archive.
// Controlled if `open`/`onOpenChange` are supplied, else self-managed.
// When `groupByProject` is set, time cards are filed into per-project folders
// (collapsible) with an hours/OT subtotal each, plus a grand-total summary.
function LibraryMenu({ label, newLabel, items, activeId, onOpen, onDelete, onNew, open: openProp, onOpenChange, groupByProject, summary }) {
  const controlled = typeof openProp === 'boolean';
  const [openState, setOpenState] = React.useState(false);
  const open = controlled ? openProp : openState;
  const setOpen = (v) => {
    const next = typeof v === 'function' ? v(open) : v;
    if (controlled) onOpenChange(next); else setOpenState(next);
  };
  const [q, setQ] = React.useState('');
  const [collapsed, setCollapsed] = React.useState({});
  const ref = React.useRef(null);
  React.useEffect(() => {
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    window.addEventListener('mousedown', h);
    return () => window.removeEventListener('mousedown', h);
  }, [open]);
  React.useEffect(() => { if (!open) setQ(''); }, [open]);

  const needle = q.trim().toLowerCase();
  const filtered = needle
    ? items.filter(it => (it.title + ' ' + it.sub).toLowerCase().includes(needle))
    : items;
  const showSearch = items.length > 6;
  const fmtH = (window.fmtHours || ((h) => String(Math.round((h || 0) * 10) / 10)));

  // Build folders (preserves item order = recency) when grouping is on.
  const groups = [];
  if (groupByProject) {
    const idx = {};
    for (const it of filtered) {
      const key = it.project || it.title || 'Untitled';
      if (idx[key] == null) { idx[key] = groups.length; groups.push({ name: key, items: [], hours: 0, ot: 0 }); }
      const g = groups[idx[key]];
      g.items.push(it); g.hours += (it.hours || 0); g.ot += (it.ot || 0);
    }
  }
  const toggleGroup = (name) => setCollapsed(c => ({ ...c, [name]: !c[name] }));

  const renderRow = (it) => (
    <li key={it.id} className={'saved-item' + (it.id === activeId ? ' on' : '')} onClick={() => { onOpen(it.id); setOpen(false); }}>
      <div className="si-main">
        <div className="si-title">{it.title}</div>
        <div className="si-sub mono">{it.sub}{groupByProject && it.hours > 0 ? ` · ${fmtH(it.hours)}h${it.ot > 0 ? ` · ${fmtH(it.ot)} OT` : ''}` : ''}</div>
      </div>
      <button className="si-del" title="Delete" onClick={(e) => { e.stopPropagation(); onDelete(it.id); }}>✕</button>
    </li>
  );

  return (
    <div className="lib-menu" ref={ref}>
      <button className="lib-trigger" onClick={() => setOpen(o => !o)}>
        Saved <span className="lib-count">{items.length}</span> <span className="lib-caret">▾</span>
      </button>
      {open && (
        <div className="lib-panel">
          <button className="btn btn-primary" onClick={() => { onNew(); setOpen(false); }}>+ New {newLabel}</button>
          {groupByProject && summary && summary.cards > 0 && (
            <div className="lib-summary">
              <div className="lib-sum-main">
                <span className="lsm-num mono">{fmtH(summary.hours)}<span className="lsm-u">h</span></span>
                <span className="lsm-lbl">total worked</span>
              </div>
              {summary.ot > 0 && (
                <div className="lib-sum-ot">
                  <span className="lso-num mono">{fmtH(summary.ot)}<span className="lsm-u">h</span></span>
                  <span className="lsm-lbl">overtime</span>
                </div>
              )}
              <div className="lib-sum-meta mono">{summary.cards} {summary.cards === 1 ? 'card' : 'cards'} · {summary.projects} {summary.projects === 1 ? 'show' : 'shows'}</div>
            </div>
          )}
          {showSearch && (
            <input className="lib-search" type="text" value={q} autoFocus
              placeholder={'Search ' + label.toLowerCase() + '…'}
              onChange={e => setQ(e.target.value)} />
          )}
          {items.length === 0 && <p className="muted sm pad">Nothing saved yet.</p>}
          {items.length > 0 && filtered.length === 0 && <p className="muted sm pad">No matches for “{q}”.</p>}
          {groupByProject ? (
            <div className="lib-groups">
              {groups.map(g => {
                const isCollapsed = !!collapsed[g.name];
                return (
                  <div className="lib-group" key={g.name}>
                    <button className="lg-head" onClick={() => toggleGroup(g.name)}>
                      <span className={'caret' + (isCollapsed ? '' : ' open')}>▸</span>
                      <span className="lg-name" title={g.name}>{g.name}</span>
                      <span className="lg-count mono">{g.items.length}</span>
                      <span className="lg-hrs mono">{fmtH(g.hours)}h{g.ot > 0 ? ` · ${fmtH(g.ot)} OT` : ''}</span>
                    </button>
                    {!isCollapsed && <ul className="saved-list">{g.items.map(renderRow)}</ul>}
                  </div>
                );
              })}
            </div>
          ) : (
            <ul className="saved-list">{filtered.map(renderRow)}</ul>
          )}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { LibraryDock, LibraryMenu });
