/* === PHYSL 210 — app shell + routing === */
const { useState: useSA, useEffect: useEA } = React;

const MoonGlyph = () => (
  <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M20 14.4A8 8 0 1 1 9.6 4 6.5 6.5 0 0 0 20 14.4Z" />
  </svg>
);
const SunGlyph = () => (
  <svg width="19" height="19" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.9" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <circle cx="12" cy="12" r="4" /><path d="M12 2.6v2.2M12 19.2v2.2M2.6 12h2.2M19.2 12h2.2M5.1 5.1l1.6 1.6M17.3 17.3l1.6 1.6M18.9 5.1l-1.6 1.6M6.7 17.3l-1.6 1.6" />
  </svg>
);
const BurgerGlyph = () => (
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
    <path d="M4 7h16M4 12h16M4 17h16" />
  </svg>
);
const CloseGlyph = () => (
  <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
    <path d="M6 6l12 12M18 6L6 18" />
  </svg>
);

/* Dark-mode toggle — requests a change via the 'physl-dark' event; tweaks.jsx is the
   single applier and echoes 'physl-dark-set' so this icon stays in sync with the panel. */
function DarkToggle() {
  const [dark, setDark] = useSA(() => { try { return localStorage.getItem('physl.dark') === '1'; } catch (e) { return false; } });
  useEA(() => {
    const onSet = (e) => setDark(!!(e && e.detail));
    window.addEventListener('physl-dark-set', onSet);
    return () => window.removeEventListener('physl-dark-set', onSet);
  }, []);
  const toggle = () => {
    const v = !dark;
    setDark(v);
    try { window.dispatchEvent(new CustomEvent('physl-dark', { detail: v })); } catch (e) {}
  };
  return (
    <button className="nav-dark" onClick={toggle} aria-pressed={dark} aria-label="Toggle dark mode"
      title={dark ? 'Switch to light mode' : 'Switch to dark mode'}>
      {dark ? <SunGlyph /> : <MoonGlyph />}
    </button>
  );
}

function TopNav({ page, go, user, onSignOut }) {
  const who = user || STUDENT;
  const [menuOpen, setMenuOpen] = useSA(false);
  const changePw = async () => {
    const oldPassword = window.prompt('Current password:'); if (!oldPassword) return;
    const newPassword = window.prompt('New password (at least 8 characters):'); if (!newPassword) return;
    const res = await window.physlAuth.changePassword(oldPassword, newPassword);
    window.alert(res.ok ? 'Password changed.' : ('Could not change password: ' + (res.error || 'error')));
  };
  // close the mobile menu on Escape, and whenever the viewport grows back to desktop
  useEA(() => {
    if (!menuOpen) return;
    const onKey = (e) => { if (e.key === 'Escape') setMenuOpen(false); };
    const mq = window.matchMedia('(min-width: 921px)');
    const onWide = (e) => { if (e.matches) setMenuOpen(false); };
    window.addEventListener('keydown', onKey);
    try { mq.addEventListener('change', onWide); } catch (e) { mq.addListener && mq.addListener(onWide); }
    return () => {
      window.removeEventListener('keydown', onKey);
      try { mq.removeEventListener('change', onWide); } catch (e) { mq.removeListener && mq.removeListener(onWide); }
    };
  }, [menuOpen]);
  const navTo = (key) => { setMenuOpen(false); go(key); };
  // full set of destinations for the mobile menu (brand also goes Home, but list it for clarity)
  const menuItems = [{ key:'home', label:'Home' }, { key:'schedule', label:'Schedule' }, ...SECTIONS];
  return (
    <div className="nav">
      <div className="nav-brand" onClick={() => navTo('home')}>
        <HeartMark size={30} />
        <span className="wm">PHYSL <span style={{ color:'var(--coral)' }}>210</span></span>
      </div>
      <div className="nav-tabs">
        {[{ key:'schedule', label:'Schedule' }, ...SECTIONS].map(s => (
          <button key={s.key} className={`nav-tab${page===s.key ? ' active' : ''}`} onClick={() => go(s.key)}>{s.label}</button>
        ))}
      </div>
      <div className="nav-right">
        <DarkToggle />
        {/* account controls — shown inline on desktop, folded into the mobile menu on phones */}
        <div className="nav-acct-group">
          <div className="avatar" title={who} style={{ cursor:'pointer' }} onClick={() => go('home')}>{String(who)[0].toUpperCase()}</div>
          {user && <button className="nav-acct" onClick={changePw} title="Change password">Password</button>}
          {user && <button className="nav-acct" onClick={onSignOut} title={`Sign out ${who}`}>Sign out</button>}
        </div>
        <button className="nav-burger" aria-label={menuOpen ? 'Close menu' : 'Open menu'} aria-expanded={menuOpen}
          onClick={() => setMenuOpen(o => !o)}>
          {menuOpen ? <CloseGlyph /> : <BurgerGlyph />}
        </button>
      </div>
      {menuOpen && (
        <>
          <div className="nav-menu-backdrop" onClick={() => setMenuOpen(false)} aria-hidden="true" />
          <nav className="nav-menu" aria-label="Sections">
            {menuItems.map(s => (
              <button key={s.key} className={`nav-menu-item${page===s.key ? ' active' : ''}`} onClick={() => navTo(s.key)}>{s.label}</button>
            ))}
            {user && <div className="nav-menu-div" />}
            {user && <button className="nav-menu-item nav-menu-acct" onClick={() => { setMenuOpen(false); changePw(); }}>Change password</button>}
            {user && <button className="nav-menu-item nav-menu-acct" onClick={() => { setMenuOpen(false); onSignOut(); }}>Sign out</button>}
          </nav>
        </>
      )}
    </div>
  );
}

function App({ user, onSignOut }) {
  const [route, setRoute] = useSA(() => ({ page: localStorage.getItem('physl.page') || 'home', focus: null, n: 0 }));
  const go = (page, focus = null) => { setRoute(r => ({ page, focus, n: r.n + 1 })); window.scrollTo(0, 0); };
  useEA(() => { localStorage.setItem('physl.page', route.page); }, [route.page]);

  const { page, focus, n } = route;
  const k = `${page}-${n}`;
  let body;
  if (page === 'home') body = <HomePage key={k} go={go} user={user} />;
  else if (page === 'schedule') body = <SchedulePage key={k} go={go} />;
  else if (page === 'lessons') body = <LessonsPage key={k} focus={focus} go={go} />;
  else if (page === 'notes') body = <NotesPage key={k} focus={focus} go={go} />;
  else if (page === 'practice') body = <PracticePage key={k} focus={focus} go={go} />;
  else if (page === 'exam') body = <ExamPage key={k} go={go} />;
  else if (page === 'cards') body = <FlashcardsPage key={k} focus={focus} go={go} />;
  else if (page === 'progress') body = <ProgressPage key={k} go={go} />;
  else body = <HomePage key={k} go={go} />;

  return (
    <div className="phys-root app">
      <TopNav page={page} go={go} user={user} onSignOut={onSignOut} />
      <main style={{ flex:1 }}>{body}</main>
      <Tweaks />
    </div>
  );
}

/* ---- login gate: each user signs in, then their progress is pulled from the server ---- */
function LoginScreen({ onLoggedIn }) {
  const [u, setU] = useSA('');
  const [p, setP] = useSA('');
  const [err, setErr] = useSA('');
  const [busy, setBusy] = useSA(false);
  const submit = async (e) => {
    e.preventDefault();
    if (busy || !u.trim() || !p) return;
    setBusy(true); setErr('');
    const res = await window.physlAuth.login(u.trim(), p);
    if (res.ok) { try { await window.physlAuth.pull(); } catch (e2) {} onLoggedIn(u.trim()); return; }
    setBusy(false);
    setErr(res.status === 429 ? 'Too many attempts — please wait a few minutes.'
      : res.error === 'network' ? 'Network error — check your connection.'
      : 'Incorrect username or password.');
  };
  return (
    <div className="login-wrap">
      <div className="login-glow" aria-hidden="true" />
      <form className="login-card fade" onSubmit={submit}>
        <div className="login-brand"><HeartMark size={38} /><span className="wm">PHYSL <span style={{ color:'var(--coral)' }}>210</span></span></div>
        <h1 className="login-title">Welcome back</h1>
        <p className="login-sub">Sign in to track your own progress — synced across your devices.</p>
        <div className="login-field">
          <label htmlFor="li-user" className="login-label">Username</label>
          <input id="li-user" className="login-input" autoFocus autoComplete="username" placeholder="your username" value={u} onChange={(e) => setU(e.target.value)} />
        </div>
        <div className="login-field">
          <label htmlFor="li-pass" className="login-label">Password</label>
          <input id="li-pass" className="login-input" type="password" autoComplete="current-password" placeholder="••••••••" value={p} onChange={(e) => setP(e.target.value)} />
        </div>
        {err && <div className="login-err">{err}</div>}
        <button className="btn btn-primary login-btn" type="submit" disabled={busy}>{busy ? 'Signing in…' : 'Sign in →'}</button>
      </form>
      <div className="login-foot">PHYSL <span style={{ color:'var(--coral)' }}>210</span> · your physiology study companion</div>
    </div>
  );
}

function Root() {
  const [status, setStatus] = useSA('loading'); // 'loading' | 'login' | 'app'
  const [user, setUser] = useSA(null);
  useEA(() => {
    let alive = true;
    (async () => {
      let who = null;
      try { who = await window.physlAuth.me(); } catch (e) {}
      if (!alive) return;
      if (who) { try { await window.physlAuth.pull(); } catch (e) {} if (!alive) return; setUser(who); setStatus('app'); }
      else setStatus('login');
    })();
    return () => { alive = false; };
  }, []);
  if (status === 'loading') return <div className="login-wrap"><div className="login-loading">Loading…</div></div>;
  if (status === 'login') return <LoginScreen onLoggedIn={(who) => { setUser(who); setStatus('app'); }} />;
  const onSignOut = async () => { try { await window.physlAuth.logout(); } catch (e) {} location.reload(); };
  return <App user={user} onSignOut={onSignOut} />;
}

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