/* ============ helpers.jsx — shared helpers & small components ============ */

/* color palettes assigned to book covers based on region/subject */
window.coverPaletteFor = function(book){
  const R = book.region;
  const S = book.subject;
  const palettes = {
    'GWR':         { bg:'#6b3419', fg:'#efdfb3', spine:'#3c1c0c' },
    'LNER':        { bg:'#0e3a2a', fg:'#ded3a8', spine:'#072017' },
    'LMS':         { bg:'#57161a', fg:'#ecd9b8', spine:'#2e0a0c' },
    'SR':          { bg:'#2a3e4d', fg:'#e3d7b0', spine:'#13212a' },
    'BR':          { bg:'#243243', fg:'#e0d4ab', spine:'#111a24' },
    'Modern':      { bg:'#2d2f2e', fg:'#d7ccab', spine:'#16181a' },
    'Narrow gauge':{ bg:'#3a2a18', fg:'#e7d5ac', spine:'#1a120a' },
    'Continental': { bg:'#1d3538', fg:'#e0d1a5', spine:'#0a1718' },
    'Pre-grouping':{ bg:'#3d1f2b', fg:'#e8d6af', spine:'#1d0c13' },
  };
  if (palettes[R]) return palettes[R];
  const subjPalettes = {
    'Modelling':    { bg:'#1f3a2b', fg:'#ecdcb3', spine:'#0c1c14' },
    'Electrics':    { bg:'#3a3d18', fg:'#ebdfb2', spine:'#1c1d0a' },
    'Signalling':   { bg:'#4e2b14', fg:'#eadaad', spine:'#28150a' },
    'Scenery':      { bg:'#2e4228', fg:'#e9daad', spine:'#17220f' },
    'Layout design':{ bg:'#43362a', fg:'#eddcb0', spine:'#241b13' },
  };
  return subjPalettes[S] || { bg:'#2a2f25', fg:'#e2d3a6', spine:'#13160f' };
};

window.daysBetween = function(a, b){
  const A = new Date(a), B = new Date(b);
  return Math.round((B - A) / (1000*60*60*24));
};
window.today = () => new Date();
window.fmtDate = function(iso){
  if (!iso) return '';
  const d = new Date(iso);
  if (isNaN(d)) return iso;
  return d.toLocaleDateString('en-GB', { day:'2-digit', month:'short', year:'numeric' });
};

/* Bookplate cover */
window.Bookplate = function Bookplate({ book, onClick, compact }) {
  const pal = window.coverPaletteFor(book);
  const onLoanFully = book.copies - book.onLoan <= 0;
  return (
    <div
      className={"bookplate" + (onLoanFully ? " on-loan" : "")}
      style={{
        "--cover-bg": pal.bg,
        "--cover-fg": pal.fg,
        "--cover-spine": pal.spine,
        color: pal.fg,
      }}
      onClick={onClick}
      title={book.title}
    >
      <span className="bp-availability"/>
      <div className="bp-region">{book.region !== '—' ? book.region : book.subject}</div>
      <div className="bp-title">{book.title}</div>
      <div className="bp-author">{book.author}</div>
      <div className="bp-foot">
        <span>{book.year}</span>
        <span>{book.scale !== '—' ? book.scale : (book.subject || '').slice(0,3).toUpperCase()}</span>
      </div>
    </div>
  );
};

window.AvailabilityLine = function AvailabilityLine({ book }){
  const avail = book.copies - book.onLoan;
  if (avail > 0) {
    return (
      <div className="r-avail on-shelf">
        <span className="dot"/> On shelf · {avail} of {book.copies}
      </div>
    );
  }
  return (
    <div className="r-avail on-loan">
      <span className="dot"/> On loan — reserve
    </div>
  );
};

window.BrassRule = function BrassRule(){
  return (
    <div className="hero-rule">
      <span className="line"/><span className="diamond"/><span className="line"/>
    </div>
  );
};

window.SectionHead = function SectionHead({ eyebrow, title, action, onAction }){
  return (
    <div className="section-head">
      <div>
        {eyebrow && <span className="eyebrow">{eyebrow}</span>}
        <h2>{title}</h2>
      </div>
      {action && <a className="view-all" onClick={onAction}>{action} →</a>}
    </div>
  );
};

window.Masthead = function Masthead({ route, go, session, isAdmin }){
  const active = (r) => route.name === r ? 'active' : '';
  return (
    <header className="masthead">
      <div className="masthead-inner">
        <div className="crest" onClick={() => go({name:'home'})}>
          <div className="monogram">MR<br/>S</div>
          <div>
            <div>The Society Library</div>
            <div className="society-line">South Devon Model Railway Society · Est. 1947</div>
          </div>
        </div>
        <nav className="nav">
          <a className={active('home')}    onClick={() => go({name:'home'})}>Search</a>
          <a className={active('browse')}  onClick={() => go({name:'browse'})}>Browse</a>
          <a className={active('account')} onClick={() => session ? go({name:'account'}) : go({name:'login'})}>My Loans</a>
          {isAdmin && <a className={active('librarian')} onClick={() => go({name:'librarian'})}>Librarian</a>}
        </nav>
        <div className="nav-divider"/>
        {session ? (
          <div className="acct-chip" onClick={() => go({name:'account'})}>
            <span className="dot"/>{(session.name || '').split(' ').slice(-1)[0] || 'Member'}
          </div>
        ) : (
          <div className="acct-chip" onClick={() => go({name:'login'})}>
            <span className="dot"/>Sign in
          </div>
        )}
      </div>
    </header>
  );
};

window.Footer = function Footer({ stats }){
  return (
    <footer className="foot">
      <div className="foot-inner">
        <div className="col">
          <h4>The South Devon Model Railway Society Library</h4>
          <div>Mon / Wed / Fri · Clubhouse, 19:00–21:30</div>
          <div>2nd Saturday · 10:00–13:00</div>
          <div className="motto">“Light a lamp. Open a book. Run a train.”</div>
        </div>
        <div className="col">
          <h4>Catalogue</h4>
          <div>{stats?.total ?? '—'} volumes</div>
          <div>{stats?.onLoan ?? '—'} currently on loan</div>
          <div>{stats?.addedThisYear ?? '—'} added this year</div>
        </div>
        <div className="col">
          <h4>Contact</h4>
          <div>Librarian: the on-duty admin</div>
          <div>library@mcmrs.org.uk</div>
          <div>Library card no. on request</div>
        </div>
      </div>
    </footer>
  );
};

window.Tweaks = function Tweaks({ theme, setTheme, visible }){
  if (!visible) return null;
  const themes = [
    { id:'green',    name:'Bottle',  chip:'#1f3a2b' },
    { id:'oxblood',  name:'Oxblood', chip:'#5a1a19' },
    { id:'midnight', name:'Midnight',chip:'#1a2a4a' },
  ];
  return (
    <aside className="tweaks">
      <h4><span>Tweaks</span> <span style={{opacity:0.6}}>Colour theme</span></h4>
      <div className="swatches">
        {themes.map(t => (
          <button
            key={t.id}
            className={"sw " + (theme === t.id ? "active" : "")}
            onClick={() => setTheme(t.id)}
          >
            <span className="chip" style={{ color: t.chip }}/>{t.name}
          </button>
        ))}
      </div>
    </aside>
  );
};

/* ---- Shared API helper (used by all pages) ----
   Calls Cloudflare Pages Functions under /api/* with the Clerk bearer token. */
window.api = async function api(path, opts = {}){
  let token = '';
  try {
    if (window.Clerk && window.Clerk.session) {
      token = await window.Clerk.session.getToken();
    }
  } catch(e){ /* signed-out routes still work */ }
  const headers = { ...(opts.headers || {}) };
  if (token) headers['Authorization'] = 'Bearer ' + token;
  const res = await fetch(path, { ...opts, headers });
  if (res.status === 204) return null;
  const text = await res.text();
  let body; try { body = JSON.parse(text); } catch { body = text; }
  if (!res.ok) {
    const msg = body && body.error ? body.error : (typeof body === 'string' ? body : ('HTTP ' + res.status));
    const err = new Error(msg); err.status = res.status; err.body = body;
    throw err;
  }
  return body;
};

/* Clerk SignIn widget mount helper — used by the Login page */
window.mountClerkSignIn = function mountClerkSignIn(el){
  if (!el || !window.Clerk) return;
  try { window.Clerk.mountSignIn(el); } catch(e){ console.error('mountSignIn:', e); }
};
window.unmountClerkSignIn = function unmountClerkSignIn(el){
  if (!el || !window.Clerk) return;
  try { window.Clerk.unmountSignIn(el); } catch(e){}
};
