// Small shared UI for live collaboration: who's here, and the "/" chat
// bubble that follows your cursor (Figma-style). Used by Rooms + Sheets.

// Chips showing the other people on this room / sheet.
function LivePeers({ peers = [], compact = false }) {
  if (!peers.length) return null;
  return (
    <div className={`live-peers${compact ? ' is-compact' : ''}`} title={peers.map(p => p.name).join(', ') + (peers.length === 1 ? ' is here' : ' are here')}>
      {peers.map(p => (
        <span key={p.id} className="live-peer" style={{ '--c': p.color }}>
          <i className="live-peer-dot" />{compact ? p.name.slice(0, 1) : p.name}
        </span>
      ))}
      {!compact && <span className="live-peers-txt">{peers.length === 1 ? 'is here' : 'are here'}</span>}
    </div>
  );
}

// Fixed-position chat input pinned where the mouse was when "/" was
// pressed. Calls onChange on every keystroke (so the other person sees
// you typing), onSend on Enter, onClose on Escape / blur.
function LiveChatInput({ x, y, color, onChange, onSend, onClose }) {
  const [val, setVal] = React.useState('');
  const ref = React.useRef(null);
  React.useEffect(() => { ref.current && ref.current.focus(); }, []);
  const left = Math.max(8, Math.min(x + 14, window.innerWidth - 280));
  const top = Math.max(8, Math.min(y + 14, window.innerHeight - 60));
  return (
    <div className="live-chat" style={{ left, top, '--c': color }}>
      <span className="live-chat-tail" />
      <input
        ref={ref}
        type="text"
        value={val}
        placeholder="Say something… (Enter to send, Esc to close)"
        onChange={(e) => { setVal(e.target.value); onChange(e.target.value); }}
        onKeyDown={(e) => {
          if (e.key === 'Enter') { e.preventDefault(); if (val.trim()) onSend(val.trim()); setVal(''); onClose(); }
          else if (e.key === 'Escape') { e.preventDefault(); onChange(''); onClose(); }
          e.stopPropagation();
        }}
        onBlur={() => { if (!val.trim()) { onChange(''); onClose(); } }}
      />
    </div>
  );
}

// Remote bubble: what the other person is typing / just sent.
function LiveBubble({ text, color, name, style }) {
  if (!text) return null;
  return (
    <div className="live-bubble" style={{ '--c': color, ...(style || {}) }}>
      <span className="live-bubble-name">{name}</span>
      <span className="live-bubble-txt">{text}</span>
    </div>
  );
}

// Hook: returns { chat, openChatAt, setChat } and manages fade-outs for
// remote messages. `send` is the live channel's send function.
function useLiveChat(sendRef) {
  const [chat, setChat] = React.useState(null);          // { x, y } — my open input
  const [remote, setRemote] = React.useState({});        // { [uid]: { text, final, at, name, color, ...pos } }
  const timers = React.useRef({});
  const onRemoteChat = (p, from) => {
    setRemote(r => ({ ...r, [from]: { ...p, at: Date.now() } }));
    if (timers.current[from]) clearTimeout(timers.current[from]);
    if (p.final || !p.text) {
      timers.current[from] = setTimeout(() => setRemote(r => { const n = { ...r }; delete n[from]; return n; }), p.final ? 5000 : 50);
    }
  };
  const openChatAt = (x, y) => setChat({ x, y });
  const broadcast = (text, final, pos) => { const s = sendRef.current; if (s) s('chat', { text, final: !!final, ...(pos || {}) }); };
  return { chat, setChat, openChatAt, remote, onRemoteChat, broadcast };
}

window.LivePeers = LivePeers;
window.LiveChatInput = LiveChatInput;
window.LiveBubble = LiveBubble;
window.useLiveChat = useLiveChat;

// Everyone else who's online in the app, with where they are.
function useGlobalPeers() {
  const [peers, setPeers] = React.useState(() => window.__mr_peers || []);
  React.useEffect(() => {
    const on = (e) => setPeers((e && e.detail) || window.__mr_peers || []);
    window.addEventListener('mr-presence', on);
    return () => window.removeEventListener('mr-presence', on);
  }, []);
  return peers;
}

const MR_ROUTE_LABELS = { discover: 'Discover', add: 'Add by link', essentials: 'Lists Library', lists: 'Lists', sheets: 'Sheets', rooms: 'Rooms', timeline: 'Timeline', interests: 'Interests', activities: 'Activities', collections: 'Library', list2: 'List', list: 'List', settings: 'Settings', admin: 'Admin' };
function peerWhere(p) {
  const base = MR_ROUTE_LABELS[p.route] || (p.route ? p.route.charAt(0).toUpperCase() + p.route.slice(1) : 'around');
  return p.label ? `${base} · ${p.label}` : base;
}

// Top-nav chip: "Lucie · Sheets · Nursery & Gear". Click → go where she is.
function PresenceNav({ onGo, following = null, onFollow = null }) {
  const peers = useGlobalPeers();
  if (!peers.length) return null;
  return (
    <div className="presence-nav">
      {peers.map(p => (
        <span key={p.id} className={`presence-chip${following === p.id ? ' is-following' : ''}`} style={{ '--c': p.color }}>
          <button type="button" className="presence-chip-go" title={`${p.name} is on ${peerWhere(p)} — click to go there`}
            onClick={() => { if (p.hash) { if (onGo) onGo(p.hash); else window.location.hash = p.hash; } }}>
            <i className="live-peer-dot" />
            <span className="presence-chip-name">{p.name}</span>
            <span className="presence-chip-where">{peerWhere(p)}</span>
          </button>
          {onFollow && (
            <button type="button" className="presence-chip-follow" onClick={() => onFollow(p.id)} title={following === p.id ? 'Stop following' : `Follow ${p.name} — your view moves with theirs until you navigate`}>
              {following === p.id ? 'Following' : 'Follow'}
            </button>
          )}
        </span>
      ))}
    </div>
  );
}

// Small "here now" marker for a room / list / sheet entry. `match(p)`
// decides whether a given peer counts as being on that thing.
function PresenceDot({ match, compact = false }) {
  const peers = useGlobalPeers().filter(match);
  if (!peers.length) return null;
  return (
    <span className="presence-dot" title={peers.map(p => p.name).join(', ') + (peers.length === 1 ? ' is here now' : ' are here now')}>
      {peers.map(p => <i key={p.id} style={{ '--c': p.color }} />)}
      {!compact && <span>{peers.map(p => p.name).join(' & ')}</span>}
    </span>
  );
}
// Match helpers: on a specific list (sheet or list page) / on a specific room.
const peerOnList = (listId) => (p) => (p.route === 'sheets' || p.route === 'list2' || p.route === 'list') && p.param === listId;
const peerOnRoom = (roomId) => (p) => p.route === 'rooms' && p.roomId === roomId;

window.useGlobalPeers = useGlobalPeers;
window.PresenceNav = PresenceNav;
window.PresenceDot = PresenceDot;
window.peerOnList = peerOnList;
window.peerOnRoom = peerOnRoom;
