/* Shared UI pieces. Icons are inline SVG paths so the app never fetches an
   icon font (and works with no network on the server). */

const ICONS = {
  board: 'M4 4h6v16H4zM14 4h6v9h-6z',
  list: 'M4 6h16M4 12h16M4 18h16',
  users: 'M16 20v-1a4 4 0 0 0-4-4H7a4 4 0 0 0-4 4v1M9.5 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7M21 20v-1a4 4 0 0 0-3-3.87M16 4.13a4 4 0 0 1 0 7.75',
  building: 'M4 21V5a1 1 0 0 1 1-1h9a1 1 0 0 1 1 1v16M15 10h4a1 1 0 0 1 1 1v10M3 21h18M8 8h3M8 12h3M8 16h3',
  video: 'M15 10l6-3v10l-6-3zM3 7a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z',
  image: 'M3 5h18v14H3zM3 15l5-5 4 4 3-3 6 6',
  plus: 'M12 5v14M5 12h14',
  bell: 'M18 8a6 6 0 1 0-12 0c0 7-3 8-3 8h18s-3-1-3-8M13.7 21a2 2 0 0 1-3.4 0',
  back: 'M19 12H5M12 19l-7-7 7-7',
  check: 'M20 6L9 17l-5-5',
  x: 'M18 6L6 18M6 6l12 12',
  upload: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M17 8l-5-5-5 5M12 3v12',
  external: 'M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14L21 3',
  clock: 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 6v6l4 2',
  settings: 'M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z',
  comment: 'M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z',
  menu: 'M3 12h18M3 6h18M3 18h18',
  trash: 'M3 6h18M8 6V4a1 1 0 0 1 1-1h6a1 1 0 0 1 1 1v2M19 6l-1 14a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1L5 6',
  drive: 'M8 3h8l6 10-4 7H6l-4-7zM8 3l-6 10M16 3l-6 10-4 7',
  pen: 'M12 19l7-7 3 3-7 7-3-3zM18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5zM2 2l7.586 7.586',
  calendar: 'M8 2v4M16 2v4M3 10h18M5 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z',
  target: 'M12 22a10 10 0 1 0 0-20 10 10 0 0 0 0 20zM12 18a6 6 0 1 0 0-12 6 6 0 0 0 0 12zM12 14a2 2 0 1 0 0-4 2 2 0 0 0 0 4z',
};

function Icon({ name, size = 17, color = 'currentColor', strokeWidth = 1.8 }) {
  const d = ICONS[name];
  if (!d) return null;
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color}
         strokeWidth={strokeWidth} strokeLinecap="round" strokeLinejoin="round" style={{ flex: 'none' }}>
      <path d={d} />
    </svg>
  );
}

function Avatar({ user, size }) {
  if (!user) return <div className={'avatar' + (size === 'lg' ? ' lg' : '')} title="Unassigned">–</div>;
  return (
    <div className={'avatar' + (size === 'lg' ? ' lg' : '')} title={user.name || user.email}>
      {initials(user.name || user.email)}
    </div>
  );
}

function StatusPill({ status }) {
  const color = STATUS_COLORS[status] || 'var(--text-dim)';
  return (
    <span className="status-pill" style={{ color, borderColor: color + '55', background: color + '12' }}>
      <span className="dot" style={{ background: color }} />
      {STATUS_SHORT[status] || status}
    </span>
  );
}

function EmptyState({ title, hint, action }) {
  return (
    <div className="empty">
      <h3>{title}</h3>
      {hint && <p className="small" style={{ margin: '0 0 14px' }}>{hint}</p>}
      {action}
    </div>
  );
}

function Modal({ title, onClose, children, footer, width }) {
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [onClose]);
  return (
    <div className="modal-backdrop" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="modal" style={width ? { width } : undefined}>
        <div className="modal-head">
          {title}
          <span className="spacer" />
          <button className="btn ghost sm" onClick={onClose}><Icon name="x" size={15} /></button>
        </div>
        <div className="modal-body">{children}</div>
        {footer && <div className="modal-foot">{footer}</div>}
      </div>
    </div>
  );
}

/* Toasts: a module-level queue so any screen can call toast() without props. */
let _pushToast = () => {};
function toast(message, kind) { _pushToast({ id: Math.random(), message, kind }); }

function ToastHost() {
  const [items, setItems] = React.useState([]);
  React.useEffect(() => {
    _pushToast = (t) => {
      setItems((list) => [...list, t]);
      setTimeout(() => setItems((list) => list.filter((i) => i.id !== t.id)), 4200);
    };
  }, []);
  return (
    <div className="toast-host">
      {items.map((t) => <div key={t.id} className={'toast' + (t.kind === 'error' ? ' error' : '')}>{t.message}</div>)}
    </div>
  );
}

/* Loads the reference data every screen needs (team + clients) once. */
function useDirectory() {
  const [users, setUsers] = React.useState([]);
  const [clients, setClients] = React.useState([]);
  const reload = React.useCallback(() => {
    Promise.all([api.get('/api/users'), api.get('/api/clients')])
      .then(([u, c]) => { setUsers(u); setClients(c); })
      .catch((e) => toast(e.message, 'error'));
  }, []);
  React.useEffect(reload, [reload]);
  const byId = React.useMemo(() => {
    const map = {};
    users.forEach((u) => { map[u.id] = u; });
    clients.forEach((c) => { map[c.id] = c; });
    return map;
  }, [users, clients]);
  return { users, clients, byId, reload };
}
