/**
 * App shell: rail navigation and the view switch. The home page is in Home.jsx.
 *
 * Navigation is built from real <button> elements rather than clickable divs, so
 * the whole course is reachable by keyboard and announced to a screen reader.
 */

(function () {
'use strict';

const { useState, useEffect, useCallback, useRef } = React;

const SYNC_LABEL = {
  local: 'נשמר במכשיר זה בלבד',
  pending: 'ממתין לשמירה…',
  saving: 'שומר…',
  saved: 'נשמר בחשבון ✓',
  offline: 'אין חיבור — יישמר כשיחזור'
};

const REVIEW_KEY = 'radiology-academy/review-mode';

/** The admin's review-mode switch, remembered per browser. On by default. */
function readReviewPref() {
  try { return window.localStorage.getItem(REVIEW_KEY) !== 'off'; } catch (err) { return true; }
}
function writeReviewPref(on) {
  try { window.localStorage.setItem(REVIEW_KEY, on ? 'on' : 'off'); } catch (err) { /* ignore */ }
}

function UserBar({ user, isAdmin, canReview, review, onReview, view, onAdmin, onSignOut }) {
  const [status, setStatus] = useState(window.Progress.syncStatus);
  useEffect(() => window.Progress.onStatus(setStatus), []);

  return (
    <div className="user-bar">
      <div className="user-bar__name">{user.displayName || user.email}</div>
      <div className="user-bar__email" dir="ltr">{user.email}</div>
      <div className={`user-bar__sync user-bar__sync--${status}`} role="status">{SYNC_LABEL[status] || ''}</div>
      {canReview && (
        <label className="review-toggle" title="כל המודולים והשלבים פתוחים, עם מפתח תשובות — לבדיקת התוכן">
          <input type="checkbox" checked={review} onChange={(e) => onReview(e.target.checked)} />
          <span>מצב סקירה (מנהל)</span>
        </label>
      )}
      <div className="user-bar__actions">
        {isAdmin && (
          <button type="button" className="btn btn--secondary btn--sm" aria-current={view === 'admin'} onClick={onAdmin}>
            דוח התקדמות הצוות
          </button>
        )}
        <button type="button" className="btn btn--ghost btn--sm" onClick={onSignOut}>התנתקות</button>
      </div>
    </div>
  );
}

function Rail({ regions, activeRegionId, activeLessonId, view, onHome, onCompare, onOpenLesson, progressTick, footer, review, open, onClose, railRef }) {
  return (
    <nav
      id="app-rail"
      ref={railRef}
      className={`app__rail ${open ? 'app__rail--open' : ''}`}
      aria-label="ניווט המערך"
    >
      <div className="brand">
        <span className="brand__mark" aria-hidden="true">◉</span>
        <span>מערך הדימות</span>
        {/* Phone drawer only (hidden on desktop by CSS): a visible way out for
            keyboard and screen-reader users, since the scrim covers the top bar. */}
        <button type="button" className="app__rail-close" aria-label="סגירת התפריט" onClick={onClose}>
          <span aria-hidden="true">✕</span>
        </button>
      </div>

      <div className="nav-group">
        <button
          type="button"
          className="nav-item"
          aria-current={view === 'home' ? 'page' : undefined}
          onClick={onHome}
        >
          <span className="nav-item__icon" aria-hidden="true">⌂</span>
          <span className="nav-item__label">דף הבית</span>
        </button>
        <button type="button" className="nav-item" aria-current={view === 'compare' ? 'page' : undefined} onClick={onCompare}>
          <span className="nav-item__icon" aria-hidden="true">◫</span>
          <span className="nav-item__label">השוואה בין סריקות</span>
        </button>
        <a className="nav-item" href="#coverage" aria-current={view === 'coverage' ? 'page' : undefined}>
          <span className="nav-item__icon" aria-hidden="true">▦</span>
          <span className="nav-item__label">כיסוי איברים ובקרת איכות</span>
        </a>
      </div>

      <div className="nav-group">
        <div className="nav-group__title">מודולים</div>
        {regions.map((region) => {
          const prog = window.Progress.regionProgress(region);
          // A prerequisite is a recommendation, not a lock: the learner chooses.
          const prereq = region.prerequisite && regions.find((r) => r.id === region.prerequisite);
          const suggested = !prereq || window.Progress.isRegionUnlocked(region, regions);
          const isActive = region.id === activeRegionId;

          return (
            <div key={region.id}>
              <button
                type="button"
                className="nav-item"
                aria-current={isActive}
                onClick={() => onOpenLesson(region.lessons[0].id)}
                title={suggested ? region.summary : `מומלץ לסיים קודם: ${prereq.title}`}
              >
                <span className="nav-item__icon" aria-hidden="true">{region.icon}</span>
                <span className="nav-item__label">{region.title}</span>
                <span className="nav-item__meter">
                  {`${prog.done}/${prog.total}`}
                </span>
              </button>

              {isActive &&
                region.lessons.map((lesson) => {
                  const done = window.Progress.isLessonComplete(lesson.id);
                  const current = lesson.id === activeLessonId;
                  return (
                    <button
                      key={lesson.id}
                      type="button"
                      className="nav-sub"
                      aria-current={current}
                      onClick={() => onOpenLesson(lesson.id)}
                    >
                      <span
                        className={`nav-sub__dot ${done ? 'nav-sub__dot--done' : current ? 'nav-sub__dot--active' : ''}`}
                        aria-hidden="true"
                      />
                      <span>{lesson.title}</span>
                    </button>
                  );
                })}
            </div>
          );
        })}
      </div>

      {footer}
    </nav>
  );
}

function App() {
  const regions = window.Curriculum.REGIONS;
  const cloud = window.Cloud && window.Cloud.enabled;

  // local: no Firebase config, progress stays in this browser (previous behaviour)
  // booting → signedOut | ready ; error when the SDK could not load
  const [auth, setAuth] = useState(cloud ? 'booting' : 'local');
  const [user, setUser] = useState(null);
  const [bootError, setBootError] = useState('');
  const [view, setView] = useState('home'); // home | lesson | admin
  const [lessonId, setLessonId] = useState(null);
  // The lesson picker open on the home page: a body station, the principles of
  // a modality, or the self-test. It lives in the URL so Back closes it.
  const [picker, setPicker] = useState(null);
  const [tick, setTick] = useState(0);
  const [reviewPref, setReviewPref] = useState(readReviewPref);
  // Phone width only: the rail is a drawer. On wider screens CSS keeps it
  // pinned beside the content and this flag has no visible effect.
  const [navOpen, setNavOpen] = useState(false);
  const railRef = useRef(null);
  const menuBtnRef = useRef(null);
  const wasOpenRef = useRef(false);

  const refresh = useCallback(() => setTick((t) => t + 1), []);

  useEffect(() => {
    if (!cloud) return undefined;
    let unsubscribe = () => {};
    let cancelled = false;
    // Every auth event gets a number. A sign-in whose progress is still
    // loading when a newer event arrives (sign-out in another tab, another
    // account) must not finish by marking the app ready as the old user.
    let generation = 0;

    window.Cloud.init()
      .then(() => {
        if (cancelled) return;
        unsubscribe = window.Cloud.onAuthChange(async (u) => {
          const mine = ++generation;
          if (!u) {
            await window.Progress.detach();
            if (mine !== generation) return;
            setUser(null);
            setAuth('signedOut');
            return;
          }
          setAuth('booting');
          await window.Progress.attach(u);
          if (mine !== generation || cancelled) return;
          setUser(u);
          setAuth('ready');
          refresh();
        });
      })
      .catch((err) => {
        console.error('[shell] firebase init failed', err);
        setBootError('לא ניתן היה להתחבר לשרת. בדוק את החיבור לאינטרנט ורענן את הדף.');
        setAuth('signedOut');
      });

    return () => {
      cancelled = true;
      unsubscribe();
    };
  }, [cloud, refresh]);

  // Deep links: #lesson/<id> so a specific exercise can be shared or bookmarked,
  // and #admin for the team report.
  useEffect(() => {
    function applyHash() {
      const hash = window.location.hash;
      const pick = /^#(station|principles|exam)(?:\/(.+))?$/.exec(hash);
      setPicker(pick ? { kind: pick[1], id: pick[2] ? decodeURIComponent(pick[2]) : null } : null);
      if (pick) { setView('home'); setLessonId(null); return; }
      if (hash === '#coverage') { setView('coverage'); setLessonId(null); return; }
      if (/^#compare(?:\?|$)/.test(hash)) {
        setView('compare');
        setLessonId(null);
        return;
      }
      if (hash === '#admin') {
        setView('admin');
        setLessonId(null);
        return;
      }
      const match = /^#lesson\/(.+)$/.exec(hash);
      setLessonId(match ? decodeURIComponent(match[1]) : null);
      setView(match ? 'lesson' : 'home');
    }
    applyHash();
    window.addEventListener('hashchange', applyHash);
    return () => window.removeEventListener('hashchange', applyHash);
  }, []);

  // Any navigation closes the drawer, so picking a lesson lands on the lesson
  // rather than on the menu still covering it.
  // Auth changes too: signing out from the open drawer swaps the whole app
  // for the sign-in screen, and a flag left open would keep its scroll locked.
  useEffect(() => {
    setNavOpen(false);
  }, [view, lessonId, auth]);

  useEffect(() => {
    if (!navOpen) return undefined;
    const onKey = (event) => {
      if (event.key === 'Escape') setNavOpen(false);
    };
    window.addEventListener('keydown', onKey);
    // Stop the page behind the open drawer from scrolling under the finger.
    document.body.classList.add('nav-locked');
    return () => {
      window.removeEventListener('keydown', onKey);
      document.body.classList.remove('nav-locked');
    };
  }, [navOpen]);

  // Keyboard focus follows the drawer: in when it opens, back to the menu
  // button when it closes. The background is made inert while it is open, so
  // Tab cannot wander into controls hidden behind the scrim.
  useEffect(() => {
    if (navOpen) {
      wasOpenRef.current = true;
      const first = railRef.current && railRef.current.querySelector('button:not([disabled])');
      if (first) first.focus();
    } else if (wasOpenRef.current) {
      wasOpenRef.current = false;
      if (menuBtnRef.current && menuBtnRef.current.offsetParent !== null) menuBtnRef.current.focus();
    }
  }, [navOpen]);

  // Rotating or resizing past the phone breakpoint hides the drawer UI; an
  // open flag left behind would keep the scrim and scroll lock on desktop.
  useEffect(() => {
    if (!window.matchMedia) return undefined;
    // Same query as the CSS, negated, so there is no gap at fractional widths
    // (860.5px under zoom) where neither layout's controls are visible.
    const mq = window.matchMedia('(max-width: 860px)');
    const onChange = () => { if (!mq.matches) setNavOpen(false); };
    if (mq.addEventListener) mq.addEventListener('change', onChange);
    else mq.addListener(onChange);
    return () => {
      if (mq.removeEventListener) mq.removeEventListener('change', onChange);
      else mq.removeListener(onChange);
    };
  }, []);

  const openLesson = useCallback((id) => {
    window.location.hash = `#lesson/${encodeURIComponent(id)}`;
  }, []);

  const goHome = useCallback(() => {
    window.location.hash = '';
  }, []);

  const openCompare = useCallback(() => {
    window.location.hash = '#compare';
  }, []);

  const openPicker = useCallback((kind, id) => {
    window.location.hash = id ? `#${kind}/${encodeURIComponent(id)}` : `#${kind}`;
  }, []);

  const found = view === 'lesson' && lessonId ? window.Curriculum.findLesson(lessonId) : null;

  function handleComplete(id) {
    refresh();
    const region = found.region;
    const i = region.lessons.findIndex((l) => l.id === id);
    const next = region.lessons[i + 1];
    if (next) openLesson(next.id);
    else goHome();
  }

  function handleReset() {
    const text = user
      ? 'למחוק את כל ההתקדמות שלך — שיעורים, מבחנים ותרגילים — מהחשבון ומכל המכשירים? אי אפשר לבטל.'
      : 'למחוק את כל ההתקדמות שנשמרה בדפדפן הזה? אי אפשר לבטל.';
    if (!window.confirm(text)) return;
    window.Progress.reset();
    refresh();
  }

  async function handleSignOut() {
    await window.Progress.flush();
    await window.Cloud.signOut();
    window.location.hash = '';
  }

  if (auth === 'booting') return <window.BootScreen text="טוען את ההתקדמות שלך…" />;
  if (auth === 'signedOut') return <window.AuthScreen bootError={bootError} />;

  const isAdmin = Boolean(user && window.Cloud.isAdmin(user));
  const showAdminEntry = Boolean(user && window.Cloud.isAdminEmail(user.email));
  // Review mode needs a verified admin, same as the team report. An address
  // on the list that is not verified yet only gets the report's verify prompt.
  const review = isAdmin && reviewPref;

  function toggleReview(on) {
    writeReviewPref(on);
    setReviewPref(on);
  }

  return (
    <div className="app">
      <header className="topbar" inert={navOpen ? '' : undefined}>
        <button
          ref={menuBtnRef}
          type="button"
          className="topbar__menu"
          aria-expanded={navOpen}
          aria-controls="app-rail"
          aria-label={navOpen ? 'סגירת התפריט' : 'פתיחת התפריט'}
          onClick={() => setNavOpen((o) => !o)}
        >
          <span aria-hidden="true">{navOpen ? '✕' : '☰'}</span>
        </button>
        <button type="button" className="topbar__brand" onClick={goHome}>
          <span className="brand__mark" aria-hidden="true">◉</span>
          <span>מערך הדימות</span>
        </button>
        {found && (
          <span className="topbar__context">{found.region.title}</span>
        )}
      </header>

      {navOpen && (
        <div className="app__scrim" aria-hidden="true" onClick={() => setNavOpen(false)} />
      )}

      <Rail
        open={navOpen}
        onClose={() => setNavOpen(false)}
        railRef={railRef}
        regions={regions}
        activeRegionId={found ? found.region.id : null}
        activeLessonId={lessonId}
        view={view}
        onHome={() => { setNavOpen(false); goHome(); }}
        onCompare={() => { setNavOpen(false); openCompare(); }}
        onOpenLesson={(id) => { setNavOpen(false); openLesson(id); }}
        progressTick={tick}
        review={review}
        footer={user ? (
          <UserBar
            user={user}
            isAdmin={showAdminEntry}
            canReview={isAdmin}
            review={review}
            onReview={toggleReview}
            view={view}
            onAdmin={() => { window.location.hash = '#admin'; }}
            onSignOut={handleSignOut}
          />
        ) : null}
      />

      <main className="app__main" inert={navOpen ? '' : undefined}>
        {view === 'admin' && user ? (
          <window.AdminReport
            user={user}
            regions={regions}
            onUserChange={(u) => { setUser(u); refresh(); }}
            onExit={goHome}
          />
        ) : view === 'admin' ? (
          <div className="callout callout--warn">דוח הצוות זמין רק כשהמערך מחובר ל-Firebase.</div>
        ) : view === 'coverage' ? (
          <window.CoveragePage />
        ) : view === 'compare' ? (
          <window.ComparisonWorkspace />
        ) : found ? (
          <window.LessonPlayer
            key={found.lesson.id}
            region={found.region}
            lesson={found.lesson}
            onExit={goHome}
            onComplete={handleComplete}
            onNavigateLesson={openLesson}
            review={review}
          />
        ) : (
          <window.HomePage
            key={tick}
            regions={regions}
            picker={picker}
            onPick={openPicker}
            onClosePicker={goHome}
            onOpenLesson={openLesson}
            onCompare={openCompare}
            onReset={handleReset}
            signedIn={Boolean(user)}
            review={review}
          />
        )}
      </main>
    </div>
  );
}

window.App = App;

})();
