/* ============ pages-public.jsx — home, browse, search, detail ============ */

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

/* ------------------------------------------------------------------ HOME */
window.HomePage = function HomePage({ go, data }){
  const [q, setQ] = useState('');
  const inputRef = useRef(null);
  useEffect(() => { inputRef.current?.focus(); }, []);
  const submit = (e) => {
    e?.preventDefault?.();
    go({ name:'search', q, filters:{} });
  };
  const quick = ['Gresley', 'GWR', 'DCC wiring', 'Bulleid', 'Finescale', 'Narrow gauge'];

  const books = data.books;
  const newArrivals = useMemo(
    () => [...books].sort((a,b) => (b.year||0) - (a.year||0)).slice(0,6),
    [books]
  );
  const featured = useMemo(() => {
    if (!books.length) return [];
    const picks = [0, 18, 9, 13, 24, 30].map(i => books[i % Math.max(1, books.length)]);
    return picks.filter(Boolean);
  }, [books]);

  const catGroups = {
    'Prototype History':   ['History','Lines & routes'],
    'Locomotives & Stock': ['Locomotives','Rolling stock'],
    'Modelling & How-to':  ['Modelling','Electrics','Scenery','Layout design','Kitbuilding'],
    'Infrastructure':      ['Infrastructure','Signalling','Electrification','Industrial','Technical'],
  };
  const catCounts = Object.fromEntries(
    Object.entries(catGroups).map(([name, subs]) =>
      [name, books.filter(b => subs.includes(b.subject)).length]
    )
  );

  const totalVolumes = books.length;
  const onLoanNow = books.reduce((s,b) => s + (b.onLoan||0), 0);
  const thisYear = new Date().getFullYear();
  const addedThisYear = books.filter(b => (b.created_at||'').startsWith(String(thisYear))).length;

  return (
    <>
      <section className="hero">
        <div className="hero-inner">
          <div className="hero-kicker">The Society Library · Members’ Catalogue</div>
          <window.BrassRule/>
          <h1>Every book<br/>on the <em>society’s shelves</em></h1>
          <p className="hero-sub">
            Search the society's collection on the prototype railways of Britain and the art of their recreation in miniature.
          </p>
          <form className="searchbox" onSubmit={submit}>
            <input
              ref={inputRef}
              placeholder="Search by title, author, region, scale, or call number…"
              value={q}
              onChange={e => setQ(e.target.value)}
              aria-label="Search the catalogue"
            />
            <button type="submit">Search</button>
          </form>
          <div className="hero-hints">
            <span>Try →</span>
            {quick.map(term => (
              <button key={term} onClick={() => go({name:'search', q:term, filters:{}})}>{term}</button>
            ))}
          </div>
        </div>
        <div className="hero-stats">
          <div><b>{totalVolumes.toLocaleString()}</b>Volumes catalogued</div>
          <div><b>{onLoanNow.toLocaleString()}</b>Currently on loan</div>
          <div><b>{addedThisYear.toLocaleString()}</b>Added this year</div>
        </div>
      </section>

      <section className="section">
        <window.SectionHead
          eyebrow="Dewey-adjacent classifications"
          title="Browse by category"
        />
        <div className="categories">
          {Object.entries(catCounts).map(([name,count], i) => (
            <button
              key={name}
              className="cat-tile"
              onClick={() => go({name:'browse', category: name})}
            >
              <span className="num">No. {String(i+1).padStart(2,'0')}</span>
              <span className="name">{name}</span>
              <span className="count">{count} volumes</span>
            </button>
          ))}
        </div>
      </section>

      {newArrivals.length > 0 && (
        <section className="section">
          <window.SectionHead
            eyebrow="Recently accessioned"
            title="New to the library"
            action="See all acquisitions"
            onAction={() => go({name:'search', q:'', filters:{}, sort:'new'})}
          />
          <div className="shelf">
            {newArrivals.map(b => (
              <window.Bookplate key={b.id} book={b} onClick={() => go({name:'book', id:b.id})}/>
            ))}
          </div>
        </section>
      )}

      {featured.length > 0 && (
        <section className="section">
          <window.SectionHead
            eyebrow="From the committee"
            title="Librarian’s selections"
            action="All recommendations"
            onAction={() => go({name:'browse'})}
          />
          <div className="shelf">
            {featured.map((b,i) => (
              <window.Bookplate key={b.id + '-' + i} book={b} onClick={() => go({name:'book', id:b.id})}/>
            ))}
          </div>
        </section>
      )}
    </>
  );
};


/* ------------------------------------------------- SEARCH / BROWSE results */

function matches(book, q){
  if (!q) return true;
  const hay = (
    (book.title || '') + ' ' + (book.author || '') + ' ' + (book.call || '') + ' ' +
    (book.region || '') + ' ' + (book.subject || '') + ' ' + (book.scale || '') + ' ' + (book.era || '') + ' ' +
    (book.blurb || '') + ' ' + ((book.tags || []).join(' '))
  ).toLowerCase();
  return q.toLowerCase().split(/\s+/).every(tok => hay.includes(tok));
}

window.SearchPage = function SearchPage({ go, route, data }){
  const [q, setQ] = useState(route.q || '');
  const [sort, setSort] = useState(route.sort || 'relevance');
  const [filters, setFilters] = useState(() => ({
    region:  route.filters?.region  ? [...route.filters.region]  : [],
    era:     route.filters?.era     ? [...route.filters.era]     : [],
    scale:   route.filters?.scale   ? [...route.filters.scale]   : [],
    subject: route.filters?.subject ? [...route.filters.subject] : [],
    lang:    route.filters?.lang    ? [...route.filters.lang]    : [],
    avail:   route.filters?.avail   ? [...route.filters.avail]   : [],
    year:    route.filters?.year    ? [...route.filters.year]    : [],
  }));

  const toggle = (group, val) => {
    setFilters(f => ({ ...f, [group]: f[group].includes(val) ? f[group].filter(x=>x!==val) : [...f[group], val] }));
  };
  const clearAll = () => setFilters({region:[],era:[],scale:[],subject:[],lang:[],avail:[],year:[]});

  const yearBuckets = ['Before 1980','1980–1999','2000–2009','2010–present'];
  const inYearBucket = (y, b) => {
    if (b === 'Before 1980') return y < 1980;
    if (b === '1980–1999')   return y >= 1980 && y < 2000;
    if (b === '2000–2009')   return y >= 2000 && y < 2010;
    if (b === '2010–present')return y >= 2010;
  };

  const filtered = useMemo(() => {
    let res = data.books.filter(b => {
      if (!matches(b, q)) return false;
      if (filters.region.length  && !filters.region.includes(b.region))  return false;
      if (filters.era.length     && !filters.era.includes(b.era))        return false;
      if (filters.scale.length   && !filters.scale.includes(b.scale))    return false;
      if (filters.subject.length && !filters.subject.includes(b.subject))return false;
      if (filters.lang.length    && !filters.lang.includes(b.lang))      return false;
      if (filters.avail.length){
        const onShelf = b.copies - b.onLoan > 0;
        const want = filters.avail.includes('On shelf') ? onShelf :
                     filters.avail.includes('On loan')  ? !onShelf : true;
        if (!want) return false;
      }
      if (filters.year.length && !filters.year.some(bk => inYearBucket(b.year, bk))) return false;

      if (route.category){
        const map = {
          'Prototype History':    ['History','Lines & routes'],
          'Locomotives & Stock':  ['Locomotives','Rolling stock'],
          'Modelling & How-to':   ['Modelling','Electrics','Scenery','Layout design','Kitbuilding'],
          'Infrastructure':       ['Infrastructure','Signalling','Electrification','Industrial','Technical'],
        };
        if (!map[route.category]?.includes(b.subject)) return false;
      }
      return true;
    });

    if (sort === 'new') res.sort((a,b) => (b.year||0) - (a.year||0));
    else if (sort === 'old') res.sort((a,b) => (a.year||0) - (b.year||0));
    else if (sort === 'title') res.sort((a,b) => (a.title||'').localeCompare(b.title||''));
    else if (sort === 'author') res.sort((a,b) => (a.author||'').localeCompare(b.author||''));
    return res;
  }, [q, filters, sort, data.books, route.category]);

  const countFor = (group, val) => {
    return data.books.filter(b => {
      if (!matches(b, q)) return false;
      if (group !== 'region' && filters.region.length && !filters.region.includes(b.region)) return false;
      if (group !== 'era' && filters.era.length && !filters.era.includes(b.era)) return false;
      if (group !== 'scale' && filters.scale.length && !filters.scale.includes(b.scale)) return false;
      if (group !== 'subject' && filters.subject.length && !filters.subject.includes(b.subject)) return false;
      if (group !== 'lang' && filters.lang.length && !filters.lang.includes(b.lang)) return false;
      if (group === 'region') return b.region === val;
      if (group === 'era')    return b.era === val;
      if (group === 'scale')  return b.scale === val;
      if (group === 'subject')return b.subject === val;
      if (group === 'lang')   return b.lang === val;
      if (group === 'avail'){
        const onShelf = b.copies - b.onLoan > 0;
        return val === 'On shelf' ? onShelf : !onShelf;
      }
      if (group === 'year') return inYearBucket(b.year, val);
      return false;
    }).length;
  };

  const submit = (e) => { e?.preventDefault?.(); };

  const activeChips = [];
  Object.entries(filters).forEach(([g, list]) => list.forEach(v => activeChips.push({g, v})));

  return (
    <>
      <div className="results-head">
        <form className="searchbox" onSubmit={submit} style={{ flex:1 }}>
          <input
            placeholder="Search the catalogue…"
            value={q}
            onChange={e => setQ(e.target.value)}
          />
          <button type="submit">Search</button>
        </form>
      </div>

      <div className="results-summary">
        <div>
          <b>{filtered.length}</b> {route.category ? `volumes in “${route.category}”` : `results${q ? ` for “${q}”` : ''}`}
        </div>
        <div className="sort">
          <span>Sort</span>
          <select value={sort} onChange={e => setSort(e.target.value)}>
            <option value="relevance">Relevance</option>
            <option value="new">Newest first</option>
            <option value="old">Oldest first</option>
            <option value="title">Title A–Z</option>
            <option value="author">Author A–Z</option>
          </select>
        </div>
      </div>

      <div className="results-layout">
        <aside className="facets">
          {activeChips.length > 0 && (
            <>
              <div className="chips">
                {activeChips.map((c,i) => (
                  <span className="chip" key={i}>
                    {c.v}
                    <button aria-label="remove" onClick={() => toggle(c.g, c.v)}>×</button>
                  </span>
                ))}
              </div>
              <button className="clear-all" onClick={clearAll}>Clear all filters</button>
            </>
          )}

          <FacetGroup title="Availability" opts={['On shelf','On loan']}
            selected={filters.avail} onToggle={v => toggle('avail', v)}
            count={v => countFor('avail', v)} />

          {data.regions.length > 0 && (
            <FacetGroup title="Region / Company" opts={data.regions}
              selected={filters.region} onToggle={v => toggle('region', v)}
              count={v => countFor('region', v)} />
          )}

          {data.eras.length > 0 && (
            <FacetGroup title="Era" opts={data.eras}
              selected={filters.era} onToggle={v => toggle('era', v)}
              count={v => countFor('era', v)} />
          )}

          {data.scales.length > 0 && (
            <FacetGroup title="Scale / Gauge" opts={data.scales}
              selected={filters.scale} onToggle={v => toggle('scale', v)}
              count={v => countFor('scale', v)} />
          )}

          {data.subjects.length > 0 && (
            <FacetGroup title="Subject" opts={data.subjects}
              selected={filters.subject} onToggle={v => toggle('subject', v)}
              count={v => countFor('subject', v)} />
          )}

          <FacetGroup title="Year published" opts={yearBuckets}
            selected={filters.year} onToggle={v => toggle('year', v)}
            count={v => countFor('year', v)} />

          {data.langs.length > 1 && (
            <FacetGroup title="Language" opts={data.langs}
              selected={filters.lang} onToggle={v => toggle('lang', v)}
              count={v => countFor('lang', v)} />
          )}
        </aside>

        <div className="results-list">
          {filtered.length === 0 && (
            <div className="empty">
              No matching volumes. Try broadening your search or clearing filters.
            </div>
          )}
          {filtered.map(b => (
            <div key={b.id} className="result-row" onClick={() => go({name:'book', id:b.id})}>
              <div className="mini-plate" style={{ width:90 }}>
                <window.Bookplate book={b} onClick={(e) => { e?.stopPropagation?.(); go({name:'book', id:b.id}); }}/>
              </div>
              <div className="r-body">
                <div className="r-meta">
                  <span>{b.region !== '—' ? b.region : 'General'}</span>
                  <span>{b.era !== '—' ? b.era : '—'}</span>
                  {b.scale !== '—' && <span>{b.scale}</span>}
                  <span>{b.year}</span>
                </div>
                <h3 className="r-title">{b.title}</h3>
                <div className="r-author">by {b.author}</div>
                {b.blurb && <p className="r-blurb">{b.blurb}</p>}
                <div className="r-tags">
                  {(b.tags || []).slice(0,3).map((t,i) => <span key={i} className="tag">{t}</span>)}
                  {b.subject && <span className="tag">{b.subject}</span>}
                </div>
              </div>
              <div className="r-right">
                <window.AvailabilityLine book={b}/>
                {b.call && <div className="r-call">{b.call}</div>}
              </div>
            </div>
          ))}
        </div>
      </div>
    </>
  );
};

function FacetGroup({ title, opts, selected, onToggle, count }){
  return (
    <div className="group">
      <h3>{title}</h3>
      {opts.map(v => (
        <label key={v}>
          <input type="checkbox" checked={selected.includes(v)} onChange={() => onToggle(v)}/>
          <span className="lbl">{v}</span>
          <span className="n">{count ? count(v) : ''}</span>
        </label>
      ))}
    </div>
  );
}


/* ------------------------------------------------------------- BOOK DETAIL */

window.BookDetailPage = function BookDetailPage({ go, route, data, session, onBorrow, wishlistToggle }){
  const book = data.books.find(b => String(b.id) === String(route.id));
  if (!book) return <div className="empty" style={{margin:'60px auto'}}>Volume not found.</div>;
  const pal = window.coverPaletteFor(book);
  const avail = book.copies - book.onLoan;
  const inWishlist = session && session.wishlist.includes(book.id);

  return (
    <div className="detail">
      <div>
        <div className="big-plate" style={{
          background: pal.bg, color: pal.fg,
          padding: '32px 28px',
          display:'flex', flexDirection:'column',
          position:'relative',
          fontFamily:'var(--serif-display)',
        }}>
          <div style={{ position:'absolute', inset:14, border:'1px solid currentColor', opacity:0.35}}/>
          <div style={{ position:'absolute', left:0, top:0, bottom:0, width:6, background: pal.spine }}/>
          <div style={{
            fontFamily:'var(--mono)', fontSize:10, letterSpacing:'0.28em', textTransform:'uppercase',
            opacity:0.75, marginBottom:16
          }}>{book.region !== '—' ? book.region : book.subject}</div>
          <div style={{ fontSize:26, fontWeight:500, lineHeight:1.12, flex:1, marginTop:16 }}>{book.title}</div>
          <div style={{ fontStyle:'italic', fontFamily:'var(--serif-body)', fontSize:14, opacity:0.85, marginTop:14 }}>{book.author}</div>
          <div style={{
            marginTop:14, borderTop:'1px solid currentColor', paddingTop:10,
            fontFamily:'var(--mono)', fontSize:10, letterSpacing:'0.16em', textTransform:'uppercase',
            display:'flex', justifyContent:'space-between', opacity:0.78
          }}>
            <span>{book.year}</span>
            <span>{book.scale !== '—' ? book.scale : book.subject}</span>
          </div>
        </div>
        <div className="side-meta">
          <dl>
            {book.call && <><dt>Call no.</dt><dd>{book.call}</dd></>}
            {book.pages && <><dt>Pages</dt><dd>{book.pages}</dd></>}
            <dt>Language</dt><dd>{book.lang}</dd>
            <dt>Copies</dt><dd>{book.copies} held</dd>
            <dt>On loan</dt><dd>{book.onLoan}</dd>
            <dt>Shelf</dt><dd>Bay {(book.id % 9) + 1} · {book.region !== '—' ? book.region : 'General'}</dd>
          </dl>
        </div>
      </div>

      <div>
        <div className="crumb">
          <a onClick={() => go({name:'home'})}>Library</a> <span>›</span>{' '}
          <a onClick={() => go({name:'search', q:'', filters:{region: book.region !== '—' ? [book.region] : []}})}>
            {book.region !== '—' ? book.region : book.subject}
          </a> <span>›</span>{' '}
          Volume
        </div>
        <div className="detail-kicker">{book.subject} · {book.era !== '—' ? book.era : book.year}</div>
        <h1>{book.title}</h1>
        <div className="by">by <em>{book.author}</em></div>

        <div className="availability-card">
          <div>
            <div className="avail-title">
              {avail > 0 ? `${avail} of ${book.copies} available on the shelf` : 'All copies currently on loan'}
            </div>
            <div className="avail-sub">
              {avail > 0
                ? 'Reserve online — collect at next clubhouse meeting'
                : 'You may join the queue and we’ll notify you when a copy is returned.'}
            </div>
          </div>
          <div className="btn-row">
            {avail > 0
              ? <button className="btn btn-primary"
                  onClick={() => session ? onBorrow(book) : go({name:'login', next:{name:'book', id:book.id}})}>
                  {session ? 'Reserve' : 'Sign in to reserve'}
                </button>
              : <button className="btn btn-ghost"
                  onClick={() => session ? onBorrow(book, true) : go({name:'login', next:{name:'book', id:book.id}})}>
                  Join hold queue
                </button>
            }
            {session && (
              <button
                className={"btn " + (inWishlist ? "btn-accent" : "btn-ghost")}
                onClick={() => wishlistToggle(book.id)}
              >
                {inWishlist ? 'On wishlist ✓' : 'Add to wishlist'}
              </button>
            )}
          </div>
        </div>

        {book.blurb && (
          <>
            <h3>Summary</h3>
            <p className="blurb">{book.blurb}</p>
          </>
        )}

        <h3>Members’ reviews</h3>
        <div className="empty" style={{margin:'10px 0 20px'}}>
          No reviews yet. {session && 'Be the first to share your thoughts.'}
        </div>
        {session && (
          <div style={{ marginTop: 22 }}>
            <button className="btn btn-ghost" disabled title="Reviews ship in Phase 2">Write a review</button>
          </div>
        )}
      </div>
    </div>
  );
};

Object.assign(window, {
  HomePage: window.HomePage,
  SearchPage: window.SearchPage,
  BookDetailPage: window.BookDetailPage,
});
