/* New reference views that complement the chapter index:
   Floors guide, The System (stats/races/classes), Glossary,
   "Where was I?" catch-up, Global timeline, Community, Gallery.
   All attach to window so shell.jsx can route to them.

   Reading-level seal: pages that show later-book detail read the
   shared window.useReaderLevel() (defined in shell.jsx). level 0 =
   sealed, 1..8 = "read through book N", 99 = all revealed. */
const { useState, useEffect } = React;

/* Small helper: the highest book a reader may safely see on a page that
   has no single "debut" book of its own. We always grant Book 1 as a
   freebie so a fresh visitor sees *something* rather than a wall of seals. */
function pageRevealBook(){
  const lvl = (window.__dccReaderLevel != null) ? window.__dccReaderLevel : 0;
  return Math.max(lvl, 1);
}

/* ============================ FLOORS ============================ */
function FloorsPage({go}){
  const D = window.DCC, X = window.DCCX;
  const [level] = window.useReaderLevel();
  const revealBook = Math.max(level, 1);
  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'index'})}>Index</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>Floors</span></div>
      <div className="sec-top">
        <h2><span style={{color:'var(--t-place)'}}>⌖</span> The <span className="am">Floors</span></h2>
        <p className="note">The World Dungeon has 18 levels. Detail for floors past your reading level stays sealed.</p>
      </div>
      <div className="floor-list">
        {X.FLOORS.map(f=>{
          const sealed = f.book > revealBook;
          return (
            <div key={f.n} className={'floor-card'+(sealed?' is-sealed':'')}>
              <div className="floor-n">{f.n>10?'10+':String(f.n).padStart(2,'0')}</div>
              <div className="floor-main">
                <div className="floor-head">
                  <h3 className="floor-name">{f.name}</h3>
                  <span className="floor-theme">{f.theme}</span>
                  <span className="floor-book">{f.book>=99?'Sealed':'Book '+f.book}</span>
                </div>
                {sealed ? (
                  <div className="floor-sealedmsg">▓▓ Sealed. You reach this floor in Book {f.book}. Raise your reading level in the top bar to reveal it.</div>
                ) : (
                  <React.Fragment>
                    <p className="floor-blurb">{f.blurb}</p>
                    {f.bosses && f.bosses.length>0 && (
                      <div className="floor-bosses">
                        <span className="fb-lab">Bosses</span>
                        {f.bosses.map((b,i)=>(<span className="fb-chip" key={i}>{b}</span>))}
                      </div>
                    )}
                  </React.Fragment>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div></div>
  );
}

/* Collapsible "by book" groups for the Races / Classes lists.
   The earliest book starts open; the rest start collapsed. A whole book
   group is sealed (and shown locked) when its book is past the reader's
   reading level — matching the spoiler seal used across the site. */
function RCByBook({items, kind, revealBook}){
  const order = [];
  const byBook = {};
  items.forEach(it=>{
    const b = it.book || 1;
    if(!byBook[b]){ byBook[b] = []; order.push(b); }
    byBook[b].push(it);
  });
  order.sort((a,b)=>a-b);
  const firstBook = order.length ? order[0] : 1;
  const [open, setOpen] = useState(()=> new Set([firstBook]));
  const toggle = b => setOpen(prev=>{ const n = new Set(prev); n.has(b) ? n.delete(b) : n.add(b); return n; });
  return (
    <div className="rc-books">
      {order.map(b=>{
        const isOpen = open.has(b);
        const sealed = b > revealBook;
        const list = byBook[b];
        return (
          <div className={'rc-bgroup'+(sealed?' is-sealed':'')+(isOpen?' is-open':'')} key={b}>
            <button className="rc-bhead" aria-expanded={isOpen} onClick={()=>toggle(b)}>
              <span className="rc-bcaret">{isOpen?'▾':'▸'}</span>
              <span className="rc-btitle">Book {b}</span>
              <span className="rc-bcount">{sealed ? '▓▓ sealed' : (list.length+' '+kind)}</span>
            </button>
            {isOpen && (sealed ? (
              <div className="rc-bsealed">▓▓ You reach these in Book {b}. Raise your reading level in the top bar to reveal them.</div>
            ) : (
              <div className="rc-list">
                {list.map((it,i)=>(
                  <div className="rc-item" key={i}>
                    <div className="rc-name">{it.name} {it.who && <em className="rc-who">{it.who}</em>} {it.off && <em className="rc-off">✦ off-world</em>}</div>
                    <div className="rc-note">{it.note}</div>
                  </div>
                ))}
              </div>
            ))}
          </div>
        );
      })}
    </div>
  );
}

/* ===================== THE SYSTEM (stats/races/classes) ===================== */
function SystemGuidePage({go}){
  const X = window.DCCX;
  const [level] = window.useReaderLevel();
  const revealBook = Math.max(level, 1);
  const seal = b => b && b>revealBook;
  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'index'})}>Index</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>The System</span></div>
      <div className="sec-top">
        <h2>How the <span className="am">System</span> Works</h2>
        <p className="note">A spoiler-light primer on stats, leveling, races, classes, bosses, and the show that runs it all.</p>
      </div>

      <div className="sysguide">
        {X.SYSTEM_GUIDE.map(s=>{
          const sd = seal(s.book);
          return (
          <div className={'sg-sec'+(sd?' is-sealed':'')} key={s.id}>
            <div className="sg-head"><span className="sg-glyph">{s.glyph}</span><h3>{s.title} {s.book && <em className="rc-bk">B{s.book>=99?'?':s.book}</em>}</h3></div>
            {sd ? (
              <p className="sg-body">▓▓ Later-book material. Raise your reading level to reveal.</p>
            ) : (
              <React.Fragment>
                {s.body.map((p,i)=>(<p className="sg-body" key={i}>{p}</p>))}
                {s.rows && (
                  <div className="sg-rows">
                    {s.rows.map((r,i)=>(<div className="sg-row" key={i}><b>{r.k}</b><span>{r.v}</span></div>))}
                  </div>
                )}
              </React.Fragment>
            )}
          </div>
        );})}
      </div>

      <div className="block-h" style={{marginTop:34}}>Races</div>
      <p className="note" style={{textAlign:'left',margin:'-6px 0 14px',maxWidth:720}}>
        On the third floor every crawler picks a race from hundreds of options. These are the ones the story turns on (crawler race-changes, the dungeon’s intelligent peoples, and the galactic species running the show) grouped by the book each first appears in. Beings from beyond Earth and the dungeon carry an <em className="rc-off">✦ off-world</em> tag. Book 1 is open; tap any book to expand it.
      </p>
      <RCByBook items={X.RACES} kind="races" revealBook={revealBook}/>

      <div className="block-h" style={{marginTop:34}}>Classes</div>
      <p className="note" style={{textAlign:'left',margin:'-6px 0 14px',maxWidth:720}}>
        Class is the other half of the Floor-3 build, and many crawlers specialize into advanced classes later. The base classes everyone starts from, plus every class the main cast and notable crawlers take, grouped by book.
      </p>
      <RCByBook items={X.CLASSES} kind="classes" revealBook={revealBook}/>
    </div></div>
  );
}

/* ============================ GLOSSARY ============================ */
function GlossaryPage({go}){
  const X = window.DCCX;
  const [q, setQ] = useState('');
  const qn = q.trim().toLowerCase();
  const terms = X.GLOSSARY.slice().sort((a,b)=>a.term.localeCompare(b.term))
    .filter(t=> !qn || (t.term+' '+t.def).toLowerCase().includes(qn));
  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'index'})}>Index</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>Glossary</span></div>
      <div className="sec-top">
        <h2><span style={{color:'var(--t-lore)'}}>◆</span> The <span className="am">Glossary</span></h2>
        <p className="note">{X.GLOSSARY.length} terms. Definitions are kept light on plot.</p>
      </div>
      <input className="gl-search" value={q} placeholder="Filter terms…" onChange={e=>setQ(e.target.value)}/>
      <div className="glossary">
        {terms.map((t,i)=>(
          <div className="gl-item" key={i}>
            <div className="gl-term">{t.term}{t.book && <em className="gl-bk">Book {t.book}+</em>}</div>
            <div className="gl-def">{t.def}</div>
          </div>
        ))}
        {!terms.length && <p className="note">No term matches “{q}”.</p>}
      </div>
    </div></div>
  );
}

/* ===================== "WHERE WAS I?" CATCH-UP ===================== */
function CatchUpPage({go}){
  const D = window.DCC;
  const live = D.BOOKS.filter(b=>b.status==='live');
  const [, setLevel] = window.useReaderLevel();
  const [book, setBook] = useState(live.length ? live[live.length-1].n : 1);
  const chs = D.chaptersFor(book);
  const [ch, setCh] = useState(chs.length ? chs[chs.length-1].num : 1);
  useEffect(()=>{ const c = D.chaptersFor(book); setCh(c.length ? c[c.length-1].num : 1); }, [book]);

  // Compile every chapter summary from the start up to (book, ch).
  const recap = [];
  live.filter(b=>b.n<=book).forEach(b=>{
    D.chaptersFor(b.n).forEach(c=>{
      if(b.n<book || c.num<=ch) recap.push({book:b.n, ...c});
    });
  });

  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'index'})}>Index</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>Where was I?</span></div>
      <div className="sec-top">
        <h2>Where <span className="am">Was I?</span></h2>
        <p className="note">Pick how far you’ve read. We’ll stitch the chapter recaps into one catch-up, and can set your spoiler level to match.</p>
      </div>

      <div className="catchup-bar">
        <label>Book
          <select value={book} onChange={e=>setBook(+e.target.value)}>
            {live.map(b=>(<option key={b.n} value={b.n}>Book {b.n}: {b.title}</option>))}
          </select>
        </label>
        <label>Through chapter
          <select value={ch} onChange={e=>setCh(+e.target.value)}>
            {chs.map(c=>(<option key={c.num} value={c.num}>{c.num===99?'Epilogue':('Ch. '+c.num)}: {c.title}</option>))}
          </select>
        </label>
        <button className="btn" onClick={()=>setLevel(book)}>Set my spoiler level to Book {book} ▸</button>
      </div>

      <p className="note" style={{maxWidth:680,textAlign:'left',margin:'4px 0 18px'}}>
        {recap.length} chapter{recap.length===1?'':'s'} recapped, through Book {book} {ch===99?'Epilogue':('Ch. '+ch)}.
      </p>

      <div className="recap-list">
        {recap.map((c,i)=>(
          <div className="recap-item" key={i} onClick={()=>go({view:'chapter', book:c.book, ch:c.num})}>
            <div className="recap-loc">B{c.book}·{c.num===99?'EP':('C'+c.num)}</div>
            <div className="recap-body">
              <div className="recap-title">{c.title} <span className="recap-arr">↗</span></div>
              <div className="recap-sum">{c.summary}</div>
            </div>
          </div>
        ))}
      </div>
    </div></div>
  );
}

/* ===================== GLOBAL TIMELINE ===================== */
function TimelinePage({go}){
  const X = window.DCCX;
  const [level] = window.useReaderLevel();
  const revealBook = Math.max(level, 1);
  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'index'})}>Index</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>Timeline</span></div>
      <div className="sec-top">
        <h2><span style={{color:'var(--t-event)'}}>✷</span> The <span className="am">Timeline</span></h2>
        <p className="note">The series’ major beats in order. Events past your reading level stay sealed.</p>
      </div>
      <div className="gtl">
        {X.MAJOR_TIMELINE.map((n,i)=>{
          const sealed = n.book > revealBook;
          return (
            <div className={'gtl-node'+(sealed?' is-sealed':'')} key={i}>
              <span className="gtl-dot" style={{background:'var(--t-event)'}}></span>
              <div className="gtl-meta">
                <span className="gtl-book">Book {n.book}</span>
                <span className="gtl-floor">Floor {n.floor}</span>
              </div>
              <div className="gtl-body">
                <div className="gtl-label">{n.label}</div>
                <div className="gtl-text">{sealed ? '▓▓ Sealed. This happens in Book '+n.book+'. Raise your reading level to reveal.' : n.text}</div>
              </div>
            </div>
          );
        })}
      </div>
    </div></div>
  );
}

/* ===================== COMMUNITY ===================== */
function CommunityPage({go}){
  const X = window.DCCX;
  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'home'})}>Home</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>Community</span></div>
      <div className="sec-top">
        <h2>The <span className="am">Crew</span></h2>
        <p className="note">Where the Crawlers gather, and every way to experience DCC beyond the books.</p>
      </div>

      <div className="block-h">Community</div>
      <div className="link-grid">
        {X.COMMUNITY.map((l,i)=>(
          <a className="link-card" key={i} href={l.url} target="_blank" rel="noopener noreferrer">
            <div className="link-kind">{l.kind}</div>
            <div className="link-name">{l.name} <span className="link-go">↗</span></div>
            <div className="link-blurb">{l.blurb}</div>
          </a>
        ))}
      </div>

      <div className="block-h" style={{marginTop:34}}>Beyond the books</div>
      <div className="link-grid">
        {X.ADAPTATIONS.map((l,i)=>(
          <a className="link-card" key={i} href={l.url} target="_blank" rel="noopener noreferrer">
            <div className="link-kind">{l.kind} · {l.status}</div>
            <div className="link-name">{l.name} <span className="link-go">↗</span></div>
            <div className="link-blurb">{l.blurb}</div>
          </a>
        ))}
      </div>
    </div></div>
  );
}

/* ===================== GALLERY ===================== */
function GalleryPage({go}){
  const D = window.DCC;
  const ArtThumb = window.ArtThumb;
  const [community, setCommunity] = useState(null);   // approved fan art entry-ids
  const [type, setType] = useState('all');
  const [limit, setLimit] = useState(48);

  useEffect(()=>{
    let live = true;
    fetch('/api/community').then(r=>r.ok?r.json():{entries:[]})
      .then(d=>{ if(live) setCommunity(d.entries||[]); })
      .catch(()=>{ if(live) setCommunity([]); });
    return ()=>{ live=false; };
  },[]);

  // Everything that ships with System AI concept art.
  const seed = window.DCC_SEED_ART || {};
  const arted = Object.keys(seed).map(id=>D.ENTRIES[id]).filter(Boolean);
  const types = D.INDEX_ORDER.filter(t=> arted.some(e=>e.type===t));
  const shown = (type==='all'?arted:arted.filter(e=>e.type===type));
  const commEntries = (community||[]).map(id=>D.ENTRIES[id]).filter(Boolean);

  return (
    <div className="view"><div className="wrap">
      <div className="crumbs"><a onClick={()=>go({view:'home'})}>Home</a><span className="sep">/</span><span style={{color:'var(--ink)'}}>Gallery</span></div>
      <div className="sec-top">
        <h2>The <span className="am">Gallery</span></h2>
        <p className="note">{arted.length} entries with concept art. See something you can do better? <a className="xlink" onClick={()=>go({view:'submit'})} style={{cursor:'pointer'}}>Submit your own ▸</a></p>
      </div>

      {commEntries.length>0 && (
        <React.Fragment>
          <div className="block-h">Community submissions</div>
          <div className="entry-grid" style={{marginBottom:30}}>
            {commEntries.map(e=>(
              <div key={e.id} className="ecard" style={{['--tc']:`var(--t-${e.type})`}} onClick={()=>go({view:'entry', id:e.id})}>
                <ArtThumb entry={e}/>
                <div className="ebody"><h3 className="enm">{e.name}</h3><p className="ed">{e.sub||e.desc}</p></div>
              </div>
            ))}
          </div>
        </React.Fragment>
      )}

      <div className="block-h">System AI concept art</div>
      <div className="chap-filter" style={{marginBottom:18}}>
        <button className={'cfilt'+(type==='all'?' on':'')} onClick={()=>{setType('all');setLimit(48);}}>All <i>{arted.length}</i></button>
        {types.map(t=>(
          <button key={t} className={'cfilt'+(type===t?' on':'')} style={{['--tc']:`var(--t-${t})`}}
            onClick={()=>{setType(t);setLimit(48);}}>
            {D.typeName[t]} <i>{arted.filter(e=>e.type===t).length}</i>
          </button>
        ))}
      </div>
      <div className="entry-grid">
        {shown.slice(0,limit).map(e=>(
          <div key={e.id} className="ecard" style={{['--tc']:`var(--t-${e.type})`}} onClick={()=>go({view:'entry', id:e.id})}>
            <ArtThumb entry={e}/>
            <div className="ebody"><h3 className="enm">{e.name}</h3><p className="ed">{e.sub||e.desc}</p></div>
          </div>
        ))}
      </div>
      {shown.length>limit && (
        <div style={{textAlign:'center',marginTop:24}}>
          <button className="btn ghost" onClick={()=>setLimit(l=>l+48)}>Load more ({shown.length-limit} left) ▾</button>
        </div>
      )}
    </div></div>
  );
}

window.FloorsPage = FloorsPage;
window.SystemGuidePage = SystemGuidePage;
window.GlossaryPage = GlossaryPage;
window.CatchUpPage = CatchUpPage;
window.TimelinePage = TimelinePage;
window.CommunityPage = CommunityPage;
window.GalleryPage = GalleryPage;
