// The Boardroom — application root. Routing + auth + data, composed onto the
// design-system AppShell and the committed RoomScreen.
const store = window.BR_STORE;

function App() {
  const [user, setUser] = React.useState(null);
  const [ready, setReady] = React.useState(false);
  // Seed with the six known experts so the board is NEVER empty (nav, ask-all, consults all
  // work immediately). The store refresh replaces this with the DB roster + real video counts.
  const [experts, setExperts] = React.useState(() => (window.BR ? window.BR.ROSTER.slice() : []));
  const [sessions, setSessions] = React.useState([]);
  // Default board = the WHOLE board (all six seated). One source of truth shared by the
  // composer's "Asking N" count and the board picker's toggles. A saved board (getBoard)
  // or the user toggling seats overrides this; it is never silently re-expanded.
  const [seated, setSeated] = React.useState(() => new Set(window.BR ? window.BR.ROSTER.map((e) => e.id) : []));
  const [boardSaved, setBoardSaved] = React.useState(false);
  const [needsOnboarding, setNeedsOnboarding] = React.useState(null); // null=checking, true=first-run, false=has board
  const [screen, setScreen] = React.useState({ name: "ask" });   // landing = ask the board
  const [consultTarget, setConsultTarget] = React.useState(null); // member for a 1:1 consult
  const [current, setCurrent] = React.useState(null);   // open session for the Room
  const [convening, setConvening] = React.useState(false);
  const [conveneError, setConveneError] = React.useState(false);
  const [pending, setPending] = React.useState(null);
  // Progressive render: while a query streams, `live` accumulates member cards + the
  // boardView as they arrive so the Room fills in instead of blocking on the full board.
  const [live, setLive] = React.useState(null); // { question, memberIds, responses, boardView, order }

  React.useEffect(() => {
    store.getUser().then((u) => { setUser(u); setReady(true); });
    store.onAuthChange((u) => { setUser(u); if (!u) { setScreen({ name: "ask" }); setCurrent(null); } });
  }, []);

  React.useEffect(() => {
    if (!user) return;
    store.listExperts().then(function (xs) { if (xs && xs.length) setExperts(xs); }).catch(function () {});
    store.listSessions(user.id).then(setSessions).catch(function () {});
    // First-run gate: a user with a saved board skips onboarding; one without picks a board.
    store.getBoard(user.id).then((b) => {
      if (b && b.member_ids && b.member_ids.length) { setSeated(new Set(b.member_ids)); setNeedsOnboarding(false); }
      else { setNeedsOnboarding(true); setScreen({ name: "onboarding" }); }
    }).catch(() => setNeedsOnboarding(false));
  }, [user]);

  if (!ready) return null;
  if (!user) return <AuthScreen store={store} onAuthed={setUser} />;

  const openSession = (id) => {
    setConvening(false); setConveneError(false);
    store.getSession(user.id, id).then((s) => { setCurrent(s); setScreen({ name: "room" }); });
  };
  const convene = (question, memberIds) => {
    setPending({ question: question, memberIds: memberIds });
    setConveneError(false); setConvening(true); setCurrent(null); setScreen({ name: "room" });
    setLive({ question: question, memberIds: memberIds, responses: {}, boardView: null, order: null });
    // Stream member cards in as they complete (first ~11s) rather than waiting for the whole
    // board (~30-90s). The early bytes also keep the tunnel alive — fixes the public 502.
    const handlers = {
      onMember: (slug, resp) => setLive((p) => p && Object.assign({}, p, {
        responses: Object.assign({}, p.responses, { [slug]: resp }),
      })),
      onBoardView: (bv, order) => setLive((p) => p && Object.assign({}, p, { boardView: bv, order: order })),
    };
    return window.BR_ANSWER.buildStream(question, memberIds, handlers)
      .then((answer) => store.saveSession(user.id, question, memberIds, answer))
      .then((s) => {
        setCurrent(s); setConvening(false); setLive(null);
        store.listSessions(user.id).then(setSessions).catch(function () {});
      })
      .catch(() => { setConvening(false); setLive(null); setConveneError(true); });
  };
  const retryConvene = () => { if (pending) convene(pending.question, pending.memberIds); };
  const toggleSeat = (id) => {
    setBoardSaved(false);
    setSeated((p) => { const n = new Set(p); n.has(id) ? n.delete(id) : n.add(id); return n; });
  };
  // Onboarding toggle: same flat set, capped at six (board can span categories).
  const toggleSeatCapped = (id) => {
    setBoardSaved(false);
    setSeated((p) => { const n = new Set(p); if (n.has(id)) n.delete(id); else if (n.size < 6) n.add(id); return n; });
  };
  const saveBoard = () => store.saveBoard(user.id, Array.from(seated), "My board").then(() => setBoardSaved(true));
  const finishOnboarding = () => store.saveBoard(user.id, Array.from(seated), "My board")
    .then(() => { setNeedsOnboarding(false); setScreen({ name: "ask" }); });
  const requestMember = (name) => store.requestMember(user.id, user.email, name);
  const openConsult = (m) => { setConsultTarget(m); setScreen({ name: "consult" }); };

  // Left nav (desktop rail): Past Consults, The Board, then the individual members.
  const NAV = [
    { id: "record",  icon: "layers", label: "Past Consults" },
    { id: "library", icon: "users",  label: "The Board" },
    { group: "The members" },
  ].concat(experts.map((e) => ({ id: "m:" + e.id, icon: "quote", label: e.name })))
   .concat([{ id: "request", icon: "plus", label: "Request a board member" }]);
  // Mobile bottom tabs (the rail is desktop-only; members are reached from The Board).
  const TABS = [
    { id: "ask",     icon: "gavel",  label: "Ask" },
    { id: "record",  icon: "layers", label: "Past" },
    { id: "library", icon: "users",  label: "Board" },
  ];
  const navigate = (id) => {
    setBoardSaved(false);
    if (id && id.indexOf("m:") === 0) {
      const m = experts.filter((e) => e.id === id.slice(2))[0];
      if (m) openConsult(m);
      return;
    }
    setScreen({ name: id });
  };

  // First-run gate. While the saved-board check is in flight, render nothing (avoids a flash
  // of the ask screen before onboarding). A first-run user with no board picks one first.
  if (needsOnboarding === null) return null;
  if (needsOnboarding && screen.name === "onboarding") {
    return (
      <OnboardingScreen experts={experts} seated={seated} max={6}
        onToggle={toggleSeatCapped} onConfirm={finishOnboarding} onRequestMember={requestMember} />
    );
  }

  const active = screen.name === "consult" && consultTarget ? "m:" + consultTarget.id
    : screen.name === "room" ? "record" : screen.name;

  const footer = (
    <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 8px", borderTop: "1px solid rgba(246,239,234,0.1)" }}>
      {React.createElement(window.TheBoardroomDesignSystem_4eda1b.Avatar, { name: user.email, size: "sm" })}
      <div style={{ minWidth: 0, flex: 1 }}>
        <div style={{ fontFamily: "var(--font-sans)", fontSize: 13, color: "#e7e2d8", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{user.email}</div>
        <button onClick={() => store.signOut()} style={{ background: "transparent", border: 0, color: "#8f877b", fontFamily: "var(--font-sans)", fontSize: 12, cursor: "pointer", padding: 0 }}>Sign out</button>
      </div>
    </div>
  );
  const topRight = (
    <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
      {React.createElement(window.TheBoardroomDesignSystem_4eda1b.Avatar, { name: user.email, size: "sm" })}
      <button onClick={() => store.signOut()} title={"Signed in as " + user.email}
        style={{ background: "transparent", border: "1px solid rgba(246,239,234,0.22)", borderRadius: "var(--radius-1)", color: "#e7e2d8", fontFamily: "var(--font-sans)", fontSize: 13, cursor: "pointer", padding: "9px 12px", minHeight: 40 }}>
        Sign out
      </button>
    </div>
  );

  return (
    <AppShell nav={NAV} tabs={TABS} active={active} footer={footer} topRight={topRight}
      onHome={() => setScreen({ name: "ask" })} onNavigate={navigate}>
      {screen.name === "ask" && (
        <AskComposer experts={experts} seated={seated} target={null} onSubmit={convene} />
      )}
      {screen.name === "consult" && consultTarget && (
        <AskComposer experts={experts} seated={seated} target={consultTarget}
          onBack={() => setScreen({ name: "ask" })} onSubmit={convene} />
      )}
      {screen.name === "record" && (
        <RecordScreen sessions={sessions} onOpen={openSession} onNew={() => setScreen({ name: "ask" })} />
      )}
      {/* Convening: full-screen "board is convening" only until the FIRST card arrives;
          then switch to the Room and fill member cards in progressively as they stream. */}
      {screen.name === "room" && convening && (!live || Object.keys(live.responses).length === 0) && (
        <RoomLoading question={pending && pending.question}
          members={pending && pending.memberIds} experts={experts} />
      )}
      {screen.name === "room" && convening && live && Object.keys(live.responses).length > 0 && (
        <RoomScreen streaming
          data={window.BR.buildRoomData(
            { question: live.question, member_ids: live.memberIds,
              answer: { boardView: live.boardView, responses: live.responses, order: live.order } },
            experts.length ? experts : null)}
          onAskBoard={(q, ids) => convene(q, ids)} />
      )}
      {screen.name === "room" && !convening && conveneError && (
        <RoomError onRetry={retryConvene} onBack={() => { setConveneError(false); setScreen({ name: "ask" }); }} />
      )}
      {screen.name === "room" && !convening && !conveneError && current && (
        <RoomScreen data={window.BR.buildRoomData(current, experts.length ? experts : null)}
          onAskBoard={(q, ids) => convene(q, ids)} />
      )}
      {screen.name === "library" && (
        <LibraryScreen experts={experts} seated={seated} saved={boardSaved}
          onToggle={toggleSeat} onSave={saveBoard} onConsult={openConsult} onRequestMember={requestMember} />
      )}
      {screen.name === "request" && (
        <RequestMemberScreen onRequest={requestMember} />
      )}
    </AppShell>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
