// App.jsx — root for the redesign prototype.
const { useState: useAppState, useEffect: useAppEffect, useRef: useAppRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "density": "compact",
  "homeLayout": "stacked",
  "quizLayout": "stacked"
}/*EDITMODE-END*/;

// ── Supabase singleton (created once per page load) ──────────────────────────
function getSupabaseClient() {
  if (window.__lexSupabase) return window.__lexSupabase;
  const cfg = window.LEXBIBLE_CONFIG || {};
  if (!cfg.SUPABASE_URL || cfg.SUPABASE_URL.startsWith('PASTE_') ||
      !cfg.SUPABASE_ANON_KEY || cfg.SUPABASE_ANON_KEY.startsWith('PASTE_')) {
    return null;
  }
  if (!window.supabase || !window.supabase.createClient) return null;
  window.__lexSupabase = window.supabase.createClient(
    cfg.SUPABASE_URL, cfg.SUPABASE_ANON_KEY,
    { auth: { persistSession: true, autoRefreshToken: true, detectSessionInUrl: true } },
  );
  return window.__lexSupabase;
}

function LexApp() {
  const t = window.LexTokens;
  const supabase = getSupabaseClient();
  const [session,    setSession]    = useAppState(null);
  const [authReady,  setAuthReady]  = useAppState(false);
  const [state,      setState]      = useAppState(null);
  const [dataReady,  setDataReady]  = useAppState(false);
  const [initError,  setInitError]  = useAppState('');
  const [view, setView]   = useAppState({ kind: 'library' }); // {kind:'library'} | {kind:'quiz', chapterId, quizId} | {kind:'newquiz', chapterId}
  const [tweaksOn, setTweaksOn] = useAppState(false);
  const [tweaks, setTweaks]     = useAppState(TWEAK_DEFAULTS);
  const [toast, setToast]       = useAppState(null);
  const [settingsOpen, setSettingsOpen] = useAppState(false);

  // Subscribe to Supabase auth state
  useAppEffect(() => {
    if (!supabase) { setAuthReady(true); return; }
    supabase.auth.getSession().then(({ data: { session } }) => {
      setSession(session);
      setAuthReady(true);
    });
    const { data: sub } = supabase.auth.onAuthStateChange((_event, newSession) => {
      setSession(newSession);
    });
    return () => sub.subscription.unsubscribe();
  }, [supabase]);

  // Load (or seed) the user's cloud data once we have a session.
  useAppEffect(() => {
    if (!supabase || !session) {
      window.LexStoreNew.clearCloud?.();
      setState(null);
      setDataReady(false);
      setInitError('');
      return;
    }
    let cancelled = false;
    setDataReady(false);
    setInitError('');
    (async () => {
      try {
        await window.LexStoreNew.initCloud(supabase, session.user.id);
        if (cancelled) return;
        setState(window.LexStoreNew.load());
        setDataReady(true);
      } catch (err) {
        if (cancelled) return;
        setInitError(err.message || 'Could not load your data.');
      }
    })();
    return () => { cancelled = true; };
  }, [supabase, session?.user?.id]);

  // Best-effort flush any pending save when the tab closes
  useAppEffect(() => {
    const onUnload = () => { window.LexStoreNew.flushPendingSave?.(); };
    window.addEventListener('beforeunload', onUnload);
    return () => window.removeEventListener('beforeunload', onUnload);
  }, []);

  async function signOut() {
    try { await window.LexStoreNew.flushPendingSave?.(); } catch (e) {}
    if (supabase) await supabase.auth.signOut();
    setSession(null);
  }

  // Tweaks host protocol
  useAppEffect(() => {
    const handler = e => {
      if (e.data?.type === '__activate_edit_mode')   setTweaksOn(true);
      if (e.data?.type === '__deactivate_edit_mode') setTweaksOn(false);
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  function persist(next) {
    setState(next);
    window.LexStoreNew.save(next);
  }

  const toastTimerRef = useAppRef(null);
  function showToast(msg, kind = 'info', opts = {}) {
    if (toastTimerRef.current) {
      clearTimeout(toastTimerRef.current);
      toastTimerRef.current = null;
    }
    setToast({ msg, kind, sticky: !!opts.sticky });
    if (!opts.sticky) {
      toastTimerRef.current = setTimeout(() => {
        setToast(null);
        toastTimerRef.current = null;
      }, 3200);
    }
  }

  // ── Chapter actions ─────────────────────────────────────────────────────
  const uploadingRef = useAppRef(false);
  async function onUpload(file) {
    if (uploadingRef.current) {
      showToast('Already extracting — wait a sec.', 'err');
      return;
    }
    if (state.chapters.length >= window.LexStoreNew.MAX_CHAPTERS) {
      showToast('Slot full — delete a chapter first.', 'err');
      return;
    }
    const name = (file.name || '').toLowerCase();
    if (!name.endsWith('.pdf')) {
      showToast('Only PDF files are supported.', 'err');
      return;
    }
    uploadingRef.current = true;
    showToast(`Extracting text from ${file.name}…`);
    try {
      const extracted = await window.LexExtract.extractFromFile(file);
      const id = window.LexStoreNew.genId('ch_');
      const newChapter = {
        id,
        displayName: file.name.replace(/\.[^.]+$/, '').replace(/[_-]+/g, ' '),
        sourceFilename: file.name,
        uploadedAt: Date.now(),
        ...extracted,
      };
      persist({
        ...state,
        chapters: [...state.chapters, newChapter],
        quizzes:  { ...state.quizzes, [id]: [] },
      });
      showToast(`Uploaded ${file.name} — ${extracted.pageCount} pages indexed.`);
    } catch (err) {
      console.error('[upload] extraction failed:', err);
      showToast(err.message || 'Could not extract text from this file.', 'err');
    } finally {
      uploadingRef.current = false;
    }
  }
  function onRename(id, newName) {
    persist({ ...state, chapters: state.chapters.map(c => c.id === id ? { ...c, displayName: newName } : c) });
  }
  function onDelete(id) {
    const next = { ...state.quizzes };
    delete next[id];
    persist({ ...state, chapters: state.chapters.filter(c => c.id !== id), quizzes: next });
    showToast('Chapter deleted.');
  }

  // ── Quiz actions ────────────────────────────────────────────────────────
  const generatingRef = useAppRef(false);
  function onNewQuiz(chapterId) { setView({ kind:'newquiz', chapterId }); }
  async function onCreateQuiz(chapterId, config) {
    if (generatingRef.current) {
      showToast('Already generating a quiz — wait a sec.', 'err');
      return;
    }
    const ch = state.chapters.find(c => c.id === chapterId);
    if (!ch) return;
    if (!ch.pages || !ch.pages.some(p => p.text && p.text.trim())) {
      showToast('Chapter has no extracted text — re-upload the PDF.', 'err');
      return;
    }
    generatingRef.current = true;
    setView({ kind:'library' });
    showToast(`Generating ${config.count}-question quiz from ${ch.displayName}…`, 'info', { sticky: true });
    try {
      const { questions } = await window.LexQuizGen.generateQuiz(ch, config);
      const newQuiz = {
        id: window.LexStoreNew.genId('qz_'),
        name: `${ch.displayName} — Quiz ${(state.quizzes[chapterId] || []).length + 1}`,
        config,
        createdAt: Date.now(),
        lastTaken: null,
        progress: { answered: 0, correct: 0 },
        questions,
      };
      // Re-read state at completion time — the user may have made other
      // changes while the API was running. setState's functional form would
      // be cleaner, but persist needs the full next object for cloud save.
      setState(prev => {
        const next = {
          ...prev,
          quizzes: { ...prev.quizzes, [chapterId]: [...(prev.quizzes[chapterId] || []), newQuiz] },
        };
        window.LexStoreNew.save(next);
        return next;
      });
      showToast(`Quiz ready — ${questions.length} question${questions.length === 1 ? '' : 's'} generated.`);
    } catch (err) {
      console.error('[quiz-gen] failed:', err);
      showToast(err.message || 'Quiz generation failed. Try again.', 'err');
    } finally {
      generatingRef.current = false;
    }
  }
  function onStartQuiz(chapterId, quizId) {
    setView({ kind:'quiz', chapterId, quizId });
  }
  function onDeleteQuiz(chapterId, quizId) {
    const next = { ...state.quizzes, [chapterId]: (state.quizzes[chapterId] || []).filter(q => q.id !== quizId) };
    persist({ ...state, quizzes: next });
  }
  function onUpdateActiveQuiz(chapterId, quizId, updates) {
    const next = { ...state.quizzes };
    next[chapterId] = (next[chapterId] || []).map(q => q.id === quizId ? { ...q, ...updates } : q);
    persist({ ...state, quizzes: next });
  }

  // ── Tweaks ──────────────────────────────────────────────────────────────
  function setTweak(keyOrObj, val) {
    const patch = typeof keyOrObj === 'string' ? { [keyOrObj]: val } : keyOrObj;
    const next = { ...tweaks, ...patch };
    setTweaks(next);
    window.parent.postMessage({ type:'__edit_mode_set_keys', edits: next }, '*');
  }

  // ── Auth + data gates ───────────────────────────────────────────────────────
  if (!supabase)             return <ConfigMissingScreen />;
  if (!authReady)            return <AuthLoadingScreen label="Starting up…" />;
  if (!session)              return <AuthScreen supabase={supabase} />;
  if (initError)             return <DataErrorScreen message={initError} onRetry={() => window.location.reload()} />;
  if (!dataReady || !state)  return <AuthLoadingScreen label="Loading your data…" />;

  const activeChapter = view.kind !== 'library' ? state.chapters.find(c => c.id === view.chapterId) : null;
  const activeQuiz    = view.kind === 'quiz' ? (state.quizzes[view.chapterId] || []).find(q => q.id === view.quizId) : null;

  return (
    <div style={{
      minHeight:'100vh',
      background: t.cream,
      fontFamily: t.serifBody,
      color: t.ink,
    }}>
      <TopChrome
        onHome={() => setView({ kind: 'library' })}
        userEmail={session.user.email}
        onSignOut={signOut}
        onOpenSettings={() => setSettingsOpen(true)}
      />

      <main style={{ padding: '28px 24px 64px' }}>
        {view.kind === 'library' && (
          <ChapterLibrary
            chapters={state.chapters}
            quizzes={state.quizzes}
            density={tweaks.density}
            onUpload={onUpload}
            onRename={onRename}
            onDelete={onDelete}
            onNewQuiz={onNewQuiz}
            onStartQuiz={onStartQuiz}
            onDeleteQuiz={onDeleteQuiz}
            onRenameQuiz={(chapterId, quizId, name) => onUpdateActiveQuiz(chapterId, quizId, { name })}
          />
        )}
        {view.kind === 'quiz' && activeChapter && activeQuiz && (
          <QuizPlayer
            chapter={activeChapter}
            quiz={activeQuiz}
            onExit={() => setView({ kind:'library' })}
            onUpdateQuiz={(updates) => onUpdateActiveQuiz(view.chapterId, view.quizId, updates)}
            onRenameQuiz={(newName) => onUpdateActiveQuiz(view.chapterId, view.quizId, { name: newName })}
          />
        )}
        {view.kind === 'newquiz' && activeChapter && (
          <NewQuizModal
            chapter={activeChapter}
            onCancel={() => setView({ kind:'library' })}
            onCreate={(config) => onCreateQuiz(view.chapterId, config)}
          />
        )}
      </main>

      {tweaksOn && <LexTweaksPanel tweaks={tweaks} setTweak={setTweak} onClose={() => { setTweaksOn(false); window.parent.postMessage({ type:'__edit_mode_dismissed' }, '*'); }} />}

      {settingsOpen && <SettingsModal onClose={() => setSettingsOpen(false)} />}

      {toast && <Toast {...toast} />}
    </div>
  );
}

// ── Top chrome ──────────────────────────────────────────────────────────────
function TopChrome({ onHome, userEmail, onSignOut, onOpenSettings }) {
  const t = window.LexTokens;
  const ghostBtn = {
    background:'none', border:`1px solid ${t.ruleSoft}`, borderRadius:6,
    padding:'5px 10px', fontSize:12, color: t.muted, cursor:'pointer',
    fontFamily: t.serifBody,
  };
  return (
    <header style={{
      display:'flex', alignItems:'center', justifyContent:'space-between',
      padding:'18px 32px',
      borderBottom: `1px solid ${t.ruleSoft}`,
      background: t.paper,
    }}>
      <button onClick={onHome} style={{
        background:'none', border:'none', cursor:'pointer', padding:0,
        display:'flex', alignItems:'baseline', gap:8, fontFamily: t.serifDisp,
      }}>
        <span style={{ fontSize:22, fontWeight:700, color: t.ink, letterSpacing:'-0.4px' }}>Lex<span style={{ color: t.forest }}>Bible</span></span>
      </button>
      <div style={{ display:'flex', alignItems:'center', gap:10, fontSize:12, color: t.muted, fontFamily: t.serifBody }}>
        {userEmail && <span>Signed in as <strong style={{ color: t.ink }}>{userEmail}</strong></span>}
        {onOpenSettings && (
          <button onClick={onOpenSettings} style={ghostBtn} aria-label="Settings" title="Settings">⚙ Settings</button>
        )}
        {onSignOut && (
          <button onClick={onSignOut} style={ghostBtn}>Sign out</button>
        )}
      </div>
    </header>
  );
}

// ── Loading + error screens ─────────────────────────────────────────────────
function AuthLoadingScreen({ label = 'Starting up…' }) {
  return (
    <div style={{ position:'fixed', inset:0, display:'flex', alignItems:'center', justifyContent:'center', background:'#F8F6F1', fontFamily:'"Lora", Georgia, serif', color:'#6B5B47', fontSize:14 }}>
      <div style={{ textAlign:'center' }}>
        <div style={{ width:24, height:24, border:'2.5px solid #E2D9CC', borderTopColor:'#2A6049', borderRadius:'50%', margin:'0 auto 14px', animation:'spin 0.8s linear infinite' }} />
        {label}
      </div>
    </div>
  );
}

function DataErrorScreen({ message, onRetry }) {
  return (
    <div style={{ position:'fixed', inset:0, display:'flex', alignItems:'center', justifyContent:'center', background:'#F8F6F1', fontFamily:'"Lora", Georgia, serif', padding:20 }}>
      <div style={{ background:'white', border:'1px solid #E2D9CC', borderRadius:12, padding:'28px 30px', maxWidth:440, width:'100%', boxShadow:'0 8px 32px rgba(26,39,68,.08)' }}>
        <h2 style={{ fontFamily:'"Playfair Display", Georgia, serif', fontSize:19, color:'#9B2335', margin:'0 0 10px' }}>Could not load your data</h2>
        <p style={{ fontSize:14, color:'#6B5B47', lineHeight:1.55, margin:'0 0 18px' }}>{message}</p>
        <button onClick={onRetry} style={{ padding:'9px 16px', fontSize:13, fontWeight:600, background:'#2A6049', color:'white', border:'none', borderRadius:5, cursor:'pointer', fontFamily:'inherit' }}>Retry</button>
      </div>
    </div>
  );
}

// ── Tweaks panel (custom built; the starter is loaded but we keep ours focused on the three asked) ──
function LexTweaksPanel({ tweaks, setTweak, onClose }) {
  const t = window.LexTokens;
  return (
    <div style={tweakS.panel}>
      <div style={tweakS.head}>
        <span style={tweakS.title}>Tweaks</span>
        <button style={tweakS.close} onClick={onClose}>✕</button>
      </div>

      <div style={tweakS.section}>
        <div style={tweakS.label}>Density</div>
        <div style={tweakS.seg}>
          {['compact', 'comfortable'].map(v => (
            <button key={v} onClick={() => setTweak('density', v)}
              style={{ ...tweakS.segBtn, ...(tweaks.density === v ? tweakS.segBtnOn : {}) }}>
              {v === 'compact' ? 'Compact' : 'Comfortable'}
            </button>
          ))}
        </div>
      </div>

      <div style={tweakS.section}>
        <div style={tweakS.label}>Quiz layout</div>
        <div style={tweakS.seg}>
          {[
            { v:'split',   label:'Split (question + feedback)' },
            { v:'stacked', label:'Stacked (feedback below)' },
          ].map(o => (
            <button key={o.v} onClick={() => setTweak('quizLayout', o.v)}
              style={{ ...tweakS.segBtn, ...(tweaks.quizLayout === o.v ? tweakS.segBtnOn : {}), fontSize:11 }}>
              {o.label}
            </button>
          ))}
        </div>
      </div>

      <div style={tweakS.section}>
        <div style={tweakS.label}>Home layout</div>
        <div style={tweakS.seg}>
          {[
            { v:'stacked', label:'Stacked' },
            { v:'grid',    label:'Grid (3-up)' },
          ].map(o => (
            <button key={o.v} onClick={() => setTweak('homeLayout', o.v)}
              style={{ ...tweakS.segBtn, ...(tweaks.homeLayout === o.v ? tweakS.segBtnOn : {}) }}>
              {o.label}
            </button>
          ))}
        </div>
        <div style={tweakS.hint}>Grid mode reserved for future side-by-side comparison — stacked is the default per your direction.</div>
      </div>

      <div style={tweakS.foot}>Changes apply live.</div>
    </div>
  );
}

const tweakS = {
  panel:{ position:'fixed', bottom:20, right:20, background:'#fff', border:'1px solid #E2D9CC', borderRadius:12, width:240, padding:18, boxShadow:'0 16px 44px rgba(26,23,20,0.18)', zIndex:1000, fontFamily: 'inherit' },
  head: { display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:14 },
  title:{ fontFamily:'"Playfair Display", Georgia, serif', fontWeight:700, fontSize:15, color:'#1A1714' },
  close:{ background:'none', border:'none', color:'#6B5B47', cursor:'pointer', fontSize:14 },
  section:{ marginBottom:14 },
  label:{ fontSize:10.5, fontWeight:700, color:'#2A6049', letterSpacing:'1.6px', textTransform:'uppercase', marginBottom:7 },
  seg:  { display:'flex', flexDirection:'column', gap:6 },
  segBtn:{ padding:'6px 10px', background:'none', border:'1px solid #E2D9CC', borderRadius:6, fontSize:12, color:'#1A1714', cursor:'pointer', fontFamily:'inherit', textAlign:'left' },
  segBtnOn:{ background:'#1A1714', color:'#fff', borderColor:'#1A1714' },
  hint: { marginTop:6, fontSize:10.5, color:'#8A7E6E', fontStyle:'italic', lineHeight:1.4 },
  foot: { borderTop:'1px solid #F0EAE0', paddingTop:8, marginTop:6, fontSize:10.5, color:'#B8962E' },
};

// ── Toast ───────────────────────────────────────────────────────────────────
function Toast({ msg, kind, sticky }) {
  const t = window.LexTokens;
  const map = {
    info: { bg: t.ink,    fg:'#fff' },
    err:  { bg: t.crimson, fg:'#fff' },
    flag: { bg: t.gold,    fg:'#1A1714' },
  };
  const c = map[kind] || map.info;
  return (
    <div style={{
      position:'fixed', bottom: 20, left:'50%', transform:'translateX(-50%)',
      background: c.bg, color: c.fg, padding:'10px 18px', borderRadius:10,
      fontSize:13, fontFamily: t.serifBody, fontWeight:500,
      boxShadow:'0 12px 28px rgba(26,23,20,0.25)', zIndex:1100,
      maxWidth: 480, textAlign:'center',
      display:'inline-flex', alignItems:'center', gap:10,
    }}>
      {sticky && <ToastSpinner color={c.fg} />}
      <span>{msg}</span>
    </div>
  );
}

function ToastSpinner({ color }) {
  const id = 'lex-toast-spin';
  return (
    <>
      <style>{`@keyframes ${id}{to{transform:rotate(360deg)}}`}</style>
      <span style={{
        display:'inline-block', width:14, height:14,
        border:`2px solid ${color}`, borderTopColor:'transparent',
        borderRadius:'50%', animation:`${id} .8s linear infinite`,
        flexShrink:0,
      }}/>
    </>
  );
}

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