// Live-board orchestrator (supervisor) chat — page-tier controller. Owns the project
// chat session (ensure → poll → send) and renders the pure ChatPanel docked right.
// ONE ChatPanel for orchestrator + station + create-interview (arch §3.3).
const { useState, useEffect, useRef, useCallback } = React;
const ORCH_POLL_MS = 1500;

const OrchestratorChat = ({ slug, onClose }) => {
  const [events, setEvents] = useState([]);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState(null);
  const lastSeq = useRef(0);

  useEffect(() => {
    if (!slug) return undefined;
    let alive = true, timer = null;
    const sync = async () => {
      try {
        const { events: evs } = await window.ProjectChat.getEvents(slug, lastSeq.current);
        if (alive && evs?.length) {
          lastSeq.current = evs[evs.length - 1].seq;
          setEvents((prev) => [...prev, ...evs]);
        }
      } catch (e) { if (alive) setError(e); }
      if (alive) timer = setTimeout(sync, ORCH_POLL_MS);
    };
    window.ProjectChat.ensureSession(slug)
      .then((s) => { if (!alive) return; setEvents(s.events || []); lastSeq.current = (s.events || []).at(-1)?.seq || 0; })
      .catch(setError)
      .finally(() => { if (alive) sync(); });
    return () => { alive = false; if (timer) clearTimeout(timer); };
  }, [slug]);

  const onSend = useCallback((text) => {
    setBusy(true); setError(null);
    window.ProjectChat.send(slug, text).catch(setError).finally(() => setBusy(false));
  }, [slug]);

  // The dock is bounded to the viewport, NOT to conversation length. Without a cap,
  // a long thread grows the aside to content height (measured ~1577px), drags the
  // board row past the viewport, pushes the composer below the fold, and the message
  // list's flex-1 overflow-y-auto never engages (scrollHeight === clientHeight).
  // `sticky top-[61px]` + `max-h-[calc(100vh-61px)]` cap it to the space under the
  // sticky operator AppHeader (measured 61px: py-3 + a 36px tallest control + 1px
  // border), so the list scrolls INSIDE the dock and the composer stays on-screen.
  // `self-stretch` still lets a SHORT board size the dock to the board (finding 1);
  // the viewport max-height only binds once the thread/board would overflow.
  return (
    <aside className="w-[380px] shrink-0 self-stretch sticky top-[61px] max-h-[calc(100vh-61px)] border-l border-neutral-200 bg-white flex flex-col">
      <div className="px-4 py-3 border-b border-neutral-200 flex items-center justify-between shrink-0">
        <span className="text-sm font-semibold text-neutral-900">Orchestrator</span>
        <button onClick={onClose} className="p-1.5 rounded-full hover:bg-neutral-100 text-neutral-500" aria-label="Close chat">✕</button>
      </div>
      <div className="flex-1 min-h-0">
        <window.ChatPanel events={events} phase="orchestrator" busy={busy} onSend={onSend} onGate={() => {}} contextCount={0} onToggleContext={() => {}} />
      </div>
      {error && <div className="px-4 py-2 text-xs text-red-600 border-t border-red-100">{error.message}</div>}
    </aside>
  );
};
window.OrchestratorChat = OrchestratorChat;
