/* ============================================================
   LessonDetail — THE unified lesson view (2026-06-07).

   One detail screen for every lesson regardless of entry point
   (Lessons path, Theme view, Lesson Topics grid, dashboard,
   saved items). Replaces BOTH WordGrid (track lessons) and
   TopicDetail (former Topics — now "Lesson Topics", which ARE
   lessons). Layout:

     header   — emblem + theme label + close, title, CEFR badge,
                minutes, blurb
     toggle   — Words · N | Phrases · N (hidden when only one
                list exists — "where applicable")
     cards    — every item renders the FULL universal card
                (StackedGloss: TYPE · FORMALITY header, Cyrillic,
                phonetics, literal gloss, MEANING) with heart +
                check + Listen. Base layout = the Translate page
                card per Christopher's spec; compact variants come
                in a later wave.
     footer   — progress bar + Mark lesson complete

   Progress continuity: reads the UNION of canonical + legacy
   namespaces (ru_lesson_<id> / ru_topic_<id> localStorage maps;
   user_progress item_key 'lesson:<id>:<ru>' / 'topic:<id>:<ru>')
   so pre-unification checkmarks survive. Writes go to the
   lesson's canonical namespace only.

   Data contract: window.APP.findUnifiedLesson(id) → { lesson,
   theme } (added in data.js the same day). lesson.ns is the
   canonical namespace ('lesson'|'topic'), lesson.legacy is an
   optional [{ns,id}] list of merged/alias namespaces.
   Status: ⚠️ PENDING USER TESTING
   ============================================================ */
(function () {
  const { useState, useRef, useEffect } = React;

  function lsRead(key) {
    try { return JSON.parse(localStorage.getItem(key)) || {}; } catch (e) { return {}; }
  }

  // All (ns,id) pairs whose progress this lesson owns — canonical first.
  function nsPairs(lesson) {
    const pairs = [{ ns: lesson.ns || 'lesson', id: lesson.nsId || lesson.id }];
    (lesson.legacy || []).forEach(p => pairs.push(p));
    return pairs;
  }

  function LessonDetail({ nav, lessonId, topicId }) {
    const id = lessonId || topicId;
    const found = window.APP.findUnifiedLesson ? window.APP.findUnifiedLesson(id) : null;
    const lesson = found && found.lesson;
    const theme = found && found.theme;

    // hooks run unconditionally; missing lesson handled in render
    const pairs = lesson ? nsPairs(lesson) : [];
    const canonical = pairs[0] || { ns: 'lesson', id };
    const LOCAL_KEY = 'ru_' + canonical.ns + '_' + canonical.id;

    const [view, setView] = useState(() => (lesson && (!lesson.words || !lesson.words.length) && lesson.phrases && lesson.phrases.length ? 'phrases' : 'words'));
    // 2026-06-07 — compact pass: rows render UniversalRow (compact universal
    // card); tapping a row expands the full StackedGloss brace card inline,
    // one at a time. PENDING USER TESTING
    const [expandedRu, setExpandedRu] = useState(null);
    const [learned, setLearned] = useState(() => {
      // union of canonical + legacy localStorage maps (legacy never wins over an explicit uncheck…
      // an uncheck deletes the key from the canonical map, so seed canonical LAST)
      const m = {};
      pairs.slice(1).forEach(p => Object.assign(m, lsRead('ru_' + p.ns + '_' + p.id)));
      Object.assign(m, lsRead(LOCAL_KEY));
      return m;
    });
    const [userId, setUserId] = useState(null);
    const [hint, setHint] = useState(false);

    const words = (lesson && lesson.words) || [];
    const phrases = (lesson && lesson.phrases) || [];
    const hasBoth = words.length > 0 && phrases.length > 0;
    const items = view === 'words' ? words : phrases;
    const itemKind = view === 'words' ? 'word' : 'phrase';
    const allItems = words.concat(phrases);

    // pre-warm clips on mount so Listen taps are instant
    useEffect(() => {
      if (lesson && window.warmAudio) window.warmAudio(allItems.map(it => it.say || it.ru));
    }, [id]); // eslint-disable-line

    // signed-in: union the learned set from user_progress across all namespaces
    useEffect(() => {
      let live = true;
      (async () => {
        if (!window.sb || !lesson) return;
        const { data } = await window.sb.auth.getUser();
        const uid = data && data.user ? data.user.id : null;
        if (!live) return;
        setUserId(uid);
        if (!uid) return;
        const map = {};
        for (const p of pairs) {
          const prefix = p.ns + ':' + p.id + ':';
          const { data: rows, error } = await window.sb.from('user_progress')
            .select('item_key').eq('user_id', uid).in('item_type', ['word', 'phrase']).eq('status', 'learned')
            .like('item_key', prefix + '%');
          if (error) { console.error('[lesson-detail] read', error.message); continue; }
          (rows || []).forEach(r => { const ru = r.item_key.slice(prefix.length); if (ru) map[ru] = 1; });
        }
        if (live && Object.keys(map).length) setLearned(prev => ({ ...map, ...prev, ...map }));
      })();
      return () => { live = false; };
    }, [id]); // eslint-disable-line

    const toggle = (it, kind) => {
      const wasOn = !!learned[it.ru];
      setLearned(prev => {
        const n = { ...prev };
        if (n[it.ru]) delete n[it.ru]; else n[it.ru] = 1;
        try { localStorage.setItem(LOCAL_KEY, JSON.stringify(n)); } catch (er) {}
        return n;
      });
      if (userId && window.sb) {
        const item_key = canonical.ns + ':' + canonical.id + ':' + it.ru;
        if (wasOn) {
          // delete by key WITHOUT item_type filter: legacy rows may carry
          // item_type 'word' for phrases (old wordgrid wrote 'word' for all)
          window.sb.from('user_progress').delete()
            .eq('user_id', userId).eq('item_key', item_key)
            .then(({ error }) => { if (error) console.error('[lesson-detail] delete', error.message); });
          // also clear the same ru under legacy namespaces so it can't resurrect
          pairs.slice(1).forEach(p => {
            window.sb.from('user_progress').delete()
              .eq('user_id', userId).eq('item_key', p.ns + ':' + p.id + ':' + it.ru)
              .then(({ error }) => { if (error) console.error('[lesson-detail] legacy delete', error.message); });
          });
        } else {
          window.sb.from('user_progress').upsert(
            { user_id: userId, item_type: kind, item_key, status: 'learned', completed_at: new Date().toISOString() },
            { onConflict: 'user_id,item_type,item_key' }
          ).then(({ error }) => { if (error) console.error('[lesson-detail] upsert', error.message); });
        }
      } else if (!wasOn && !userId) {
        setHint(true);
      }
    };

    // ---- graceful missing-lesson state ----------------------------
    if (!lesson) {
      return (
        <div style={{ height:'100%', display:'flex', flexDirection:'column', background:'var(--bg)' }}>
          <div style={{ padding:'50px 18px 0', display:'flex', justifyContent:'flex-end' }}>
            <IconBtn kind="close" onClick={nav.back} />
          </div>
          <div style={{ flex:1, display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
            gap:10, padding:'0 30px', textAlign:'center' }}>
            <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:22, color:'var(--ink)' }}>
              Lesson coming soon</div>
            <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:13.5, color:'var(--muted)',
              maxWidth:260, lineHeight:1.4 }}>
              This lesson isn’t ready yet — check back shortly.</div>
          </div>
        </div>
      );
    }

    const color = (theme && theme.color) || lesson.color || 'var(--primary)';
    const tint = (theme && theme.tint) || lesson.tint || 'var(--chip)';
    const total = allItems.length;
    const count = allItems.filter(it => learned[it.ru]).length;
    const isEmoji = lesson.emblem && /\p{Extended_Pictographic}/u.test(lesson.emblem);

    return (
      <div style={{ height:'100%', display:'flex', flexDirection:'column', background:'var(--bg)', position:'relative' }}>
        {/* top bar — emblem + theme label + close (mirrors WordGrid/TopicDetail) */}
        <div style={{ padding:'50px 18px 0', display:'flex', alignItems:'center', justifyContent:'space-between', gap:12 }}>
          <div style={{ display:'flex', alignItems:'center', gap:9, minWidth:0 }}>
            {isEmoji
              ? (window.TopicEmblem && <window.TopicEmblem emoji={lesson.emblem} color={color} tint={tint} size={28} radius={9} />)
              : <Emblem letter={lesson.emblem || (theme && theme.emblem) || 'Я'} color={color} size={28} radius={9} />}
            <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:700, fontSize:13.5,
              color, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{(theme && theme.name) || 'Lesson'}</span>
          </div>
          <IconBtn kind="close" onClick={nav.back} />
        </div>

        {/* title + meta + toggle + progress */}
        <div style={{ padding:'10px 22px 12px' }}>
          <div style={{ fontFamily:'"Bricolage Grotesque",system-ui', fontWeight:800, fontSize:27,
            color:'var(--ink)', letterSpacing:'-0.02em' }}>{lesson.title}</div>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginTop:5 }}>
            {lesson.cefr && lesson.cefr !== '—' && <Badge>{lesson.cefr}</Badge>}
            {lesson.minutes != null && <span style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:12.5,
              color:'var(--muted)' }}>{lesson.minutes} min</span>}
          </div>
          {lesson.blurb && <div style={{ fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:13,
            color:'var(--muted)', marginTop:6, lineHeight:1.4 }}>{lesson.blurb}</div>}
          {hasBoth && (
            <div style={{ marginTop:12 }}>
              <div style={{ display:'flex', gap:4, background:'var(--chip)', borderRadius:12, padding:4 }}>
                {[{ id:'words', label:`Words · ${words.length}` }, { id:'phrases', label:`Phrases · ${phrases.length}` }].map(o => (
                  <button key={o.id} onClick={() => { setView(o.id); setExpandedRu(null); }}
                    style={{ appearance:'none', border:'none', cursor:'pointer', flex:1, borderRadius:9,
                      padding:'9px 8px', fontFamily:'"Hanken Grotesk",system-ui', fontWeight:800, fontSize:14,
                      background: view === o.id ? 'var(--surface)' : 'transparent',
                      color: view === o.id ? 'var(--ink)' : 'var(--muted)',
                      boxShadow: view === o.id ? '0 1px 4px -1px rgba(0,0,0,0.15)' : 'none', transition:'all .15s' }}>
                    {o.label}
                  </button>
                ))}
              </div>
            </div>
          )}
          <div style={{ display:'flex', alignItems:'center', gap:12, marginTop:12 }}>
            <div style={{ flex:1 }}><Bar value={total ? count/total : 0} color={color} /></div>
            <span style={{ fontFamily:'"JetBrains Mono",monospace', fontWeight:700, fontSize:12.5,
              color:'var(--ink)', whiteSpace:'nowrap' }}>{count}<span style={{ color:'var(--muted)' }}>/{total} learned</span></span>
          </div>
        </div>

        {/* anonymous "sign in to save" hint (mirrors TopicDetail) */}
        {hint && !userId && (
          <div style={{ margin:'2px 18px 8px', display:'flex', alignItems:'center', gap:10,
            background:'var(--primary-wash)', border:'1px solid var(--line)', borderRadius:14, padding:'10px 12px' }}>
            <span style={{ flex:1, fontFamily:'"Hanken Grotesk",system-ui', fontWeight:700, fontSize:12.5, color:'var(--primary-deep)' }}>
              Sign in to save your progress</span>
            <button onClick={() => nav.go('auth')} style={{ appearance:'none', border:'none', cursor:'pointer',
              background:'var(--primary)', color:'#fff', borderRadius:999, padding:'6px 12px',
              fontFamily:'"Hanken Grotesk",system-ui', fontWeight:800, fontSize:12 }}>Sign in</button>
            <button onClick={() => setHint(false)} aria-label="Dismiss" style={{ appearance:'none', border:'none', cursor:'pointer',
              background:'transparent', color:'var(--muted)', padding:'4px', display:'flex' }}>
              <svg width="16" height="16" viewBox="0 0 24 24"><path d="M6 6l12 12M18 6L6 18" stroke="currentColor" strokeWidth="2.2" fill="none" strokeLinecap="round"/></svg>
            </button>
          </div>
        )}

        {/* the universal cards — compact rows (heart + check + speaker rail);
            row tap expands the full StackedGloss brace card inline.
            2026-06-07 — was full cards; compact per Christopher's conditional-
            formatting pass (reference screenshot). PENDING USER TESTING */}
        <div style={{ flex:1, minHeight:0, overflowY:'auto', padding:`2px 16px ${total ? 96 : 40}px`,
          display:'flex', flexDirection:'column', gap:10 }}>
          {items.length ? items.map(it => (
            <UniversalRow key={it.ru} item={it} surface={canonical.ns + ':' + canonical.id} saveKind={itemKind}
              checked={!!learned[it.ru]} onCheck={() => toggle(it, itemKind)}
              expanded={expandedRu === it.ru}
              onExpand={() => setExpandedRu(e => (e === it.ru ? null : it.ru))} />
          )) : (
            <div style={{ textAlign:'center', fontFamily:'"Hanken Grotesk",system-ui', fontWeight:600, fontSize:14,
              color:'var(--muted)', padding:'40px 20px' }}>
              No {view} in this lesson yet.</div>
          )}
        </div>

        {/* footer — Mark lesson complete (mirrors WordGrid; available for ALL lessons now) */}
        {total > 0 && (
          <div style={{ position:'absolute', left:0, right:0, bottom:0, zIndex:5,
            padding:'12px 20px calc(20px + env(safe-area-inset-bottom))', borderTop:'1px solid var(--line)',
            background:'var(--bg)', animation:'footerRise .3s cubic-bezier(.2,.9,.3,1)' }}>
            <Btn full onClick={() => {
              try { localStorage.setItem('ru_lesson_done_' + lesson.id, JSON.stringify({ at: Date.now() })); } catch (e) {}
              if (window.LessonProgress) window.LessonProgress.markDone(lesson.id);
              // 2026-06-08 — pass REAL data: learned = items actually checked
              // (was the lesson total); fake accuracy:100 dropped. PENDING USER TESTING
              nav.go('complete', { lessonId: lesson.id, learned: count });
            }}>
              Mark lesson complete
            </Btn>
          </div>
        )}
      </div>
    );
  }

  window.LessonDetail = LessonDetail;
})();
