// ============================================================================
//  App shell — auth gate, top nav, route switch, mount
// ============================================================================

function NavItem({ id, active, icon, label, onClick }) {
  return (
    <button className={`nav-item ${active ? 'active' : ''}`} onClick={onClick}>
      <span className="nav-dot"></span>{label}
    </button>
  );
}

function Shell({ session, onLogout }) {
  // route: { name, params }
  const [route, setRoute] = useState({ name: 'home' });
  const [assignMeta, setAssignMeta] = useState(null);
  // Which library folder is open on the home screen. Lifted here (not inside
  // StudentHome) so that opening a problem and hitting Back returns to the same
  // folder instead of resetting to the top-level library.
  const [folderId, setFolderId] = useState(null);
  const toast = useToast();

  // Fetch the problem's meta (title + starter) BEFORE navigating, so Solve mounts
  // with its starter ready to seed the editor.
  const openSolve = async (id) => {
    let meta = null;
    try {
      const r = await api.assignments();
      meta = r.data.assignments.find((a) => a.id === id) || null;
    } catch (e) { /* fall through with null meta */ }
    setAssignMeta(meta);
    setRoute({ name: 'solve', id });
  };

  const go = (name) => setRoute({ name });
  const isAdmin = session.role === 'admin';

  const logout = async () => { await api.logout(); onLogout(); };

  let view;
  if (route.name === 'home') view = <StudentHome onOpen={openSolve} folderId={folderId} setFolderId={setFolderId} />;
  else if (route.name === 'solve') view = <Solve key={route.id} assignmentId={route.id} meta={assignMeta} onBack={() => go('home')} />;
  else if (route.name === 'results') view = <MyResults />;
  else if (route.name === 'users') view = <AdminUsers />;
  else if (route.name === 'gradebook') view = <AdminGradebook />;

  return (
    <div className="app">
      <header className="topbar">
        <div className="brand">
          <div className="brand-mark">SC</div>
          <span className="brand-name">Stellan's Classroom</span>
          <span className="brand-tag">console</span>
        </div>

        <nav className="nav">
          <NavItem label="Assignments" active={route.name === 'home' || route.name === 'solve'} onClick={() => { setFolderId(null); go('home'); }} />
          <NavItem label="My results" active={route.name === 'results'} onClick={() => go('results')} />
          {isAdmin && <>
            <span className="nav-admin-label">admin</span>
            <NavItem label="Users" active={route.name === 'users'} onClick={() => go('users')} />
            <NavItem label="Gradebook" active={route.name === 'gradebook'} onClick={() => go('gradebook')} />
          </>}
        </nav>

        <div className="spacer"></div>

        <div className="userchip">
          <RoleBadge role={session.role} />
          <span className="uname">{session.username}</span>
          <span className="avatar">{session.username[0].toUpperCase()}</span>
        </div>
        <button className="nav-item" onClick={logout} title="Sign out" style={{ padding: 9 }}>
          <Icon name="logout" size={16} />
        </button>
      </header>

      <main className="main">{view}</main>
    </div>
  );
}

function App() {
  const [session, setSession] = useState(null);
  const [booting, setBooting] = useState(true);

  // Restore the session on load: the cookie is HttpOnly, so /me is the only way
  // to recover who we are (and whether to show the admin nav) after a refresh.
  useEffect(() => {
    api.me()
      .then((r) => setSession({ username: r.data.username, role: r.data.role }))
      .catch(() => setSession(null)) // 401 / offline → show Login
      .finally(() => setBooting(false));
  }, []);

  if (booting) {
    return <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center' }}><Spinner>Loading</Spinner></div>;
  }
  return (
    <ToastHost>
      {session
        ? <Shell session={session} onLogout={() => setSession(null)} />
        : <Login onAuthed={setSession} />}
    </ToastHost>
  );
}

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

// Once an entrance animation finishes, drop the .fade-up class so the settled
// DOM carries no re-runnable animation (keeps screenshot/PDF capture correct).
document.addEventListener('animationend', (e) => {
  if (e.target && e.target.classList && e.target.classList.contains('fade-up')) {
    e.target.classList.remove('fade-up');
  }
}, true);
