/* ============================================================
   IJMA AI — canonical texts page
   The principal works of each school, with user-fillable
   <image-slot> book covers (numbered spine until filled).
   ============================================================ */

const TEXTS_TRANSPARENT_PX = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';

/* ---- auto cover lookup: pull a freely-licensed image (manuscript / author)
   from the Wikipedia API, with guards so a generic or mismatched article is
   rejected and the numbered spine is kept instead. Nothing copyrighted is used
   (no modern printed-edition cover scans); a user drag-drop still overrides. */
const _coverCache = {};
const _deacc = s => (s || '').normalize('NFD').replace(/[̀-ͯ]/g, '');
/* normalized words (drop particles & punctuation) */
function _normT(s) {
  return _deacc(s).toLowerCase().replace(/[^a-z ]/g, ' ')
    .replace(/\b(al|ibn|abu|abi|bin|b|ben)\b/g, ' ').replace(/\s+/g, ' ').trim();
}
const _flat = s => _normT(s).replace(/ /g, '');           // spaceless, tolerates shafii/shafi'i etc.
/* a clean search query: de-diacritic, first segment, "b." -> "ibn" */
const _cleanQ = s => _deacc((s || '').split(/[;(,]/)[0]).replace(/\bb\.\s/g, 'ibn ').replace(/[ʿʾʼ’`]/g, '').replace(/\s+/g, ' ').trim();
const _GENERIC = new Set(['mukhtasar', 'sharh', 'kitab', 'risala', 'hashiya', 'matn', 'fatawa', 'sunan', 'musnad', 'majmu', 'fiqh', 'nawadir', 'tahdhib', 'jami']);
const _AUTHOR_STOP = new Set(['imam', 'shaykh', 'allama', 'muhammad', 'ahmad', 'yusuf', 'abdullah', 'abdallah', 'hasan', 'husayn', 'umar', 'uthman', 'allah', 'mahmud', 'masud', 'mansur', 'ibrahim', 'ismail', 'haramayn', 'sharia', 'committee', 'under', 'aurangzeb']);
/* the distinctive surname token of an author (longest non-common word, ≥5 chars) */
function _surname(author) {
  const toks = _normT(author).split(' ').filter(w => w.length >= 5 && !_AUTHOR_STOP.has(w));
  return toks.sort((a, b) => b.length - a.length)[0] || '';
}
/* accept a work-title match only on exact / multi-word-substring equality */
function _titleMatch(workTitle, matched) {
  const nq = _normT(workTitle), nt = _normT(matched);
  if (!nt || _GENERIC.has(nt)) return false;
  if (nq === nt) return true;
  return nq.split(' ').filter(Boolean).length >= 2 && (nt.includes(nq) || nq.includes(nt));
}
/* resolve the best-matching article title via search */
async function _wikiTitle(query) {
  const u = 'https://en.wikipedia.org/w/api.php?action=query&format=json&list=search' +
    '&srsearch=' + encodeURIComponent(query) + '&srlimit=1&srprop=&origin=*';
  const r = await fetch(u);
  if (!r.ok) return null;
  const j = await r.json();
  const s = j.query && j.query.search && j.query.search[0];
  return s ? s.title : null;
}
/* reliable thumbnail for an exact article title via the REST summary endpoint */
async function _wikiThumbByTitle(title) {
  const r = await fetch('https://en.wikipedia.org/api/rest_v1/page/summary/' + encodeURIComponent(title.replace(/ /g, '_')));
  if (!r.ok) return null;
  const j = await r.json();
  return (j.type === 'standard' && j.thumbnail) ? j.thumbnail.source : null;
}
async function lookupCover(book) {
  const key = book.title + '|' + (book.author || '');
  if (key in _coverCache) return _coverCache[key];
  let url = null;
  try {
    const wt = await _wikiTitle(_cleanQ(book.title));            // 1) the work itself
    if (wt && _titleMatch(book.title, wt)) url = await _wikiThumbByTitle(wt);
    if (!url) {                                                  // 2) else the author (surname must appear in the article title)
      const sn = _surname(book.author);
      if (sn) {
        const at = await _wikiTitle(_cleanQ(book.author));
        if (at && _flat(at).includes(sn)) url = await _wikiThumbByTitle(at);
      }
    }
  } catch (e) { url = null; }
  _coverCache[key] = url || null;
  return _coverCache[key];
}

/* group a school's flat book list into labelled sections (group appears
   on the first book of a run; later books inherit the current section). */
function sectionizeBooks(books) {
  const sections = [];
  let cur = null;
  books.forEach(b => {
    if (b.group) { cur = { label: b.group, books: [] }; sections.push(cur); }
    if (!cur) { cur = { label: null, books: [] }; sections.push(cur); }
    cur.books.push(b);
  });
  return sections;
}

function BookCard({ book, schoolId }) {
  const slotId = 'book-' + schoolId + '-' + (book.n || book.title.slice(0, 10));
  const slotRef = useRef(null);
  useEffect(() => {
    // set the image imperatively so a React re-render can't reset src; a
    // user-dropped data-URL still takes precedence inside image-slot.
    const key = schoolId + '-' + (book.n || 'x');
    const curated = window.IJMA_BOOK_COVERS && window.IJMA_BOOK_COVERS[key];
    if (curated) { if (slotRef.current) slotRef.current.setAttribute('src', curated); return; }
    let on = true;                                              // else try a live Wikimedia image
    lookupCover(book).then(url => {
      if (on && url && slotRef.current) slotRef.current.setAttribute('src', url);
    }).catch(() => {});
    return () => { on = false; };
  }, [book.title, schoolId]);
  return (
    <article className={'book-card' + (book.lost ? ' is-lost' : '')} style={schoolStyle(schoolId)}>
      <div className="book-cover-wrap">
        <span className="book-monogram" aria-hidden="true">{book.n || '—'}</span>
        <image-slot
          ref={slotRef}
          id={slotId}
          shape="rounded"
          radius="4"
          src={TEXTS_TRANSPARENT_PX}
          placeholder={book.lost ? 'lost' : 'cover'}
          style={{ width: '92px', height: '128px', display: 'block' }}
        ></image-slot>
      </div>
      <div className="book-body">
        <div className="book-title-row">
          <h3 className="book-title">{book.title}</h3>
          {book.lost && <span className="book-lost-tag">lost</span>}
        </div>
        <div className="book-author">{book.author}{book.d && <span className="book-d"> · {book.d}</span>}</div>
        {book.layer && <span className="book-layer">{book.layer}</span>}
        {book.note && <p className="book-note">{book.note}</p>}
      </div>
    </article>
  );
}

function TextsPage({ onNav }) {
  const order = D.schoolOrder;
  const [active, setActive] = useState(order[0]);
  const intro = D.textsIntro;
  const sch = D.schools[active];
  const entry = D.textSchools.find(s => s.id === active) || { books: [], blurb: '' };
  const sections = useMemo(() => sectionizeBooks(entry.books), [active]);
  const bookCount = entry.books.length;

  return (
    <main className="fade-in" style={{ maxWidth: 'var(--maxw)', margin: '0 auto', padding: '2.4rem clamp(1.2rem,4vw,3rem) 5rem' }}>
      <div className="eyebrow" style={{ marginBottom: '.6rem' }}>{intro.eyebrow}</div>
      <h1 style={{ fontSize: 'clamp(28px,3.4vw,42px)', fontWeight: 700, letterSpacing: '-0.01em', margin: '0 0 1rem', maxWidth: '22ch' }}>
        {intro.title}
      </h1>
      <p style={{ fontSize: '18px', color: 'var(--ink-2)', maxWidth: '64ch', margin: '0 0 1.2rem', lineHeight: 1.55 }}>
        {intro.lede}
      </p>
      <div className="rsch-photo-note">
        <svg width="15" height="15" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="3.5" width="12" height="9" rx="1.5"/><circle cx="5.5" cy="6.5" r="1.2"/><path d="M3 12l3.5-3 2.5 2 2-1.5L14 11"/></svg>
        Covers are drawn from scanned editions on archive.org (each matched to the work by title + author and verified on the item record), with a live Wikimedia fallback. Where no confident match exists the numbered spine stays; drag your own image onto any spine to override.
      </div>

      {/* school selector */}
      <div className="texts-school-tabs">
        {order.map(id => {
          const s = D.schools[id];
          const n = (D.textSchools.find(t => t.id === id) || { books: [] }).books.length;
          return (
            <button key={id} className={'texts-school-tab' + (active === id ? ' active' : '')}
              style={schoolStyle(id)} onClick={() => setActive(id)}>
              <span className="dot" />
              <span className="ts-name">{s.name}</span>
              <span className="ts-ar"><Ar>{s.ar}</Ar></span>
              <span className="ts-count">{n}</span>
            </button>
          );
        })}
      </div>

      {/* active school header */}
      <section key={active} className="fade-in" style={{ marginTop: '1.8rem' }}>
        <div className="texts-school-head" style={schoolStyle(active)}>
          <div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: '.6em', flexWrap: 'wrap' }}>
              <h2 style={{ fontSize: '26px', fontWeight: 700, margin: 0, color: 'var(--sc)' }}>{sch.name}</h2>
              <span style={{ fontFamily: 'var(--mono)', fontSize: '13px', color: 'var(--ink-3)' }}><Ar>{sch.ar}</Ar> · {sch.tradition}</span>
            </div>
            <div style={{ fontFamily: 'var(--mono)', fontSize: '12px', color: 'var(--ink-3)', marginTop: '.35rem' }}>
              {sch.founder} · anchor: {sch.anchor} · {bookCount} works
            </div>
          </div>
        </div>
        <p className="texts-school-blurb">{entry.blurb}</p>

        {sections.map((sec, si) => (
          <div key={si} style={{ marginTop: sec.label ? '2rem' : '1.2rem' }}>
            {sec.label && <div className="texts-group-head">{sec.label}</div>}
            <div className="book-grid">
              {sec.books.map((b, i) => <BookCard key={i} book={b} schoolId={active} />)}
            </div>
          </div>
        ))}
      </section>

      {/* citation granularity note */}
      <section style={{ marginTop: '3rem', borderTop: '1px solid var(--rule)', paddingTop: '1.6rem' }}>
        <div className="eyebrow" style={{ marginBottom: '.6rem' }}>On citation granularity</div>
        <p style={{ fontSize: '15px', color: 'var(--ink-2)', maxWidth: '70ch', lineHeight: 1.6, margin: 0 }}>
          {intro.citationNote}
        </p>
      </section>
    </main>
  );
}

Object.assign(window, { TextsPage });
