// reader-app.jsx
// Main reader application. Renders the book of eras, manages chapter navigation,
// margin notes, footnote popovers, save integration, and progress.

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

// Walks a flat block list and pairs each sidenote with the block that precedes it,
// so the page can render a two-column row (main text + margin note).
function groupBlocks(blocks) {
  const rows = [];
  for (let i = 0; i < blocks.length; i++) {
    const b = blocks[i];
    if (b.type === 'sidenote') {
      // attach to previous row if there is one and it has no sidenote yet
      const prev = rows[rows.length - 1];
      if (prev && !prev.sidenote) { prev.sidenote = b; continue; }
      // otherwise create its own row, main is a spacer
      rows.push({ main: { type: 'breath' }, sidenote: b });
    } else {
      rows.push({ main: b });
    }
  }
  return rows;
}

// =====================================================
// Era theme — returns inline style object with CSS variables for the era
// =====================================================
function eraThemeStyle(era) {
  return {
    '--era-paper': era.paper,
    '--era-paper-edge': era.paperEdge,
    '--era-ink': era.ink,
    '--era-ink-soft': era.inkSoft,
    '--era-accent': era.accent,
    '--era-family': era.family,
    '--era-body': era.bodyFamily,
    '--era-mono': era.monoFamily,
  };
}

// =====================================================
// Era motifs — small SVG markers, abstract
// =====================================================
function EraMotif({ kind, size = 56, color }) {
  const c = color || 'currentColor';
  const s = size;
  switch (kind) {
    case 'seal': // guild wax seal
      return (
        <svg width={s} height={s} viewBox="0 0 60 60" fill="none" stroke={c} strokeWidth="1">
          <circle cx="30" cy="30" r="22"/>
          <circle cx="30" cy="30" r="15"/>
          <path d="M30 15 L30 45 M15 30 L45 30 M19 19 L41 41 M41 19 L19 41" strokeWidth="0.5"/>
          <circle cx="30" cy="30" r="4" fill={c}/>
        </svg>
      );
    case 'gear':
      return (
        <svg width={s} height={s} viewBox="0 0 60 60" fill="none" stroke={c} strokeWidth="1.2">
          <circle cx="30" cy="30" r="10"/>
          <circle cx="30" cy="30" r="3" fill={c}/>
          {Array.from({ length: 8 }).map((_, i) => {
            const a = (i * Math.PI * 2) / 8;
            const x1 = 30 + Math.cos(a) * 14, y1 = 30 + Math.sin(a) * 14;
            const x2 = 30 + Math.cos(a) * 22, y2 = 30 + Math.sin(a) * 22;
            return <line key={i} x1={x1} y1={y1} x2={x2} y2={y2}/>;
          })}
        </svg>
      );
    case 'circle': // human relations — concentric rings
      return (
        <svg width={s} height={s} viewBox="0 0 60 60" fill="none" stroke={c} strokeWidth="1">
          <circle cx="30" cy="30" r="22"/>
          <circle cx="30" cy="30" r="15" strokeDasharray="2 3"/>
          <circle cx="30" cy="30" r="8"/>
          <circle cx="30" cy="30" r="2" fill={c}/>
        </svg>
      );
    case 'grid': // ledger
      return (
        <svg width={s} height={s} viewBox="0 0 60 60" fill="none" stroke={c} strokeWidth="0.8">
          {[12, 22, 32, 42].map((y) => <line key={y} x1="10" y1={y} x2="50" y2={y}/>)}
          {[12, 22, 32, 42].map((x) => <line key={x} x1={x} y1="10" x2={x} y2="50"/>)}
          <rect x="10" y="10" width="40" height="40" strokeWidth="1.2"/>
        </svg>
      );
    case 'threshold': // doorway
      return (
        <svg width={s} height={s} viewBox="0 0 60 60" fill="none" stroke={c} strokeWidth="1">
          <path d="M16 50 L16 18 Q16 10 24 10 L36 10 Q44 10 44 18 L44 50"/>
          <line x1="12" y1="50" x2="48" y2="50" strokeWidth="1.4"/>
          <line x1="30" y1="10" x2="30" y2="50" strokeDasharray="2 3"/>
        </svg>
      );
    case 'tree': // generational
      return (
        <svg width={s} height={s} viewBox="0 0 60 60" fill="none" stroke={c} strokeWidth="1">
          <line x1="30" y1="50" x2="30" y2="22"/>
          <path d="M30 22 Q22 18 18 12"/>
          <path d="M30 22 Q38 18 42 12"/>
          <path d="M30 28 Q24 26 20 22"/>
          <path d="M30 28 Q36 26 40 22"/>
          <path d="M30 34 Q26 32 24 30"/>
          <path d="M30 34 Q34 32 36 30"/>
          <circle cx="30" cy="50" r="1.5" fill={c}/>
        </svg>
      );
    default: return null;
  }
}

// =====================================================
// Block renderer — paragraph, subhead, pullquote, breath
// =====================================================
function Block({ block, era, onSidenoteClick, onSavedPassage, isSaved, saveable, highlightOpen }) {
  const ref = useRef(null);

  // Wire up footnote markers + highlight marks after render
  useEffect(() => {
    if (!ref.current) return;
    // Footnote markers
    const sups = ref.current.querySelectorAll('sup[data-note]');
    sups.forEach((sup) => {
      sup.classList.add('footnote-marker');
      sup.style.cursor = 'pointer';
      const handler = (e) => {
        e.preventDefault();
        e.stopPropagation();
        onSidenoteClick(sup.getAttribute('data-note'), sup);
      };
      sup.addEventListener('click', handler);
      sup._h = handler;
    });
    // Highlight marks
    const marks = ref.current.querySelectorAll('mark[data-key]');
    marks.forEach((m) => {
      m.classList.add('era-mark');
    });
    return () => {
      sups.forEach((sup) => sup.removeEventListener('click', sup._h));
    };
  }, [onSidenoteClick]);

  const onDragStart = useCallback((e) => {
    if (!saveable) return;
    const txt = ref.current ? ref.current.innerText.trim() : '';
    e.dataTransfer.effectAllowed = 'copy';
    e.dataTransfer.setData('text/plain', txt);
    e.dataTransfer.setData('application/x-era-save', JSON.stringify({
      kind: block.type === 'pullquote' ? 'quote' : 'bookmark',
      text: txt, eraId: era.id, eraTitle: era.title
    }));
    document.body.classList.add('is-dragging-save');
  }, [block, era, saveable]);
  const onDragEnd = useCallback(() => document.body.classList.remove('is-dragging-save'), []);

  const handleSavePassage = (kind) => {
    const txt = ref.current ? ref.current.innerText.trim() : (block.text || '');
    onSavedPassage({ kind: kind || (block.type === 'pullquote' ? 'quote' : 'bookmark'),
      text: txt, eraId: era.id, eraTitle: era.title });
  };

  const savedFlag = isSaved && ref.current ? isSaved(ref.current.innerText?.trim() || '', era.id) : false;

  switch (block.type) {
    case 'subhead':
      return (
        <h3 className="era-subhead" ref={ref}>
          <span className="era-subhead-rule" aria-hidden="true"></span>
          <span>{block.text}</span>
        </h3>
      );
    case 'p':
      return (
        <div className="era-p-wrap">
          <p
            ref={ref}
            className="era-p"
            draggable={saveable}
            onDragStart={onDragStart}
            onDragEnd={onDragEnd}
            dangerouslySetInnerHTML={{ __html: block.html }}
          />
          {saveable && (
            <BookmarkButton
              saved={savedFlag}
              onClick={() => handleSavePassage('bookmark')}
              title={savedFlag ? 'Saved (click anyway to add)' : 'Save this passage'}
            />
          )}
        </div>
      );
    case 'pullquote':
      return (
        <div className="era-pullquote-wrap">
          <blockquote
            ref={ref}
            className="era-pullquote"
            draggable={saveable}
            onDragStart={onDragStart}
            onDragEnd={onDragEnd}
            dangerouslySetInnerHTML={{ __html: block.html }}
          />
          {saveable && (
            <BookmarkButton
              saved={savedFlag}
              onClick={() => handleSavePassage('quote')}
              title="Save this quote"
            />
          )}
        </div>
      );
    case 'breath':
      return <div className="era-breath" aria-hidden="true">
        <span className="era-breath-glyph">·   ·   ·</span>
      </div>;

    case 'example':
      return (
        <div className="era-example-wrap">
          <aside className="era-example" ref={ref}
            draggable={saveable}
            onDragStart={onDragStart}
            onDragEnd={onDragEnd}
          >
            <div className="ex-label">A worked example</div>
            <div className="ex-title">{block.title}</div>
            <div className="ex-body">{block.body}</div>
          </aside>
          {saveable && (
            <BookmarkButton
              saved={savedFlag}
              onClick={() => handleSavePassage('bookmark')}
              title="Save this example"
            />
          )}
        </div>
      );

    case 'figure-trojan':
      return <FigureTrojan saveable={saveable} onSave={onSavedPassage} era={era} />;
    case 'figure-domains':
      return <FigureDomains saveable={saveable} onSave={onSavedPassage} era={era} />;
    case 'figure-bridge':
      return <FigureBridge saveable={saveable} onSave={onSavedPassage} era={era} />;
    case 'figure-translation':
      return <FigureTranslation saveable={saveable} onSave={onSavedPassage} era={era} />;
    case 'figure-compare':
      return <FigureCompare saveable={saveable} onSave={onSavedPassage} era={era} />;
    case 'figure-when':
      return <FigureWhen saveable={saveable} onSave={onSavedPassage} era={era} />;
    case 'sidenote':
      // Sidenotes render inline as anchored margin notes in book mode (Tufte-style)
      return (
        <aside
          className="era-margin-note"
          data-sidenote-id={block.id}
          onClick={() => onSidenoteClick(block.id)}
        >
          <div className="emn-label">{block.label || 'Sidenote'}</div>
          <div className="emn-title">{block.title}</div>
          <div className="emn-text">{block.text}</div>
          {block.cite && <div className="emn-cite">{block.cite}</div>}
        </aside>
      );
    default:
      return null;
  }
}

// =====================================================
// Chapter / Era page
// =====================================================
function ChapterPage({ era, idx, total, onSavedPassage, isSaved, saveable, onSidenoteClick }) {
  return (
    <article className={`chapter palette-${era.palette || 'warm'} ${era.dark ? 'is-dark' : 'is-light'}`}
      data-era={era.id} data-era-title={era.title}
      style={eraThemeStyle(era)}>
      <header className="chapter-opener">
        <div className="opener-meta">
          <div className="opener-numwrap">
            <span className="opener-num">{era.number}</span>
          </div>
          <div className="opener-chapter">{era.chapter} of {total}</div>
        </div>
        <h1 className="opener-title">{era.title}</h1>
        <div className="opener-subtitle">{era.subtitle}</div>
        <div className="opener-dates">{era.dates}</div>
        <div className="opener-motif">
          <EraMotif kind={era.motif} size={84} />
        </div>
        <div className=”opener-motto”>
          “{era.motto}”
          {era.mottoTranslation && <span className=”opener-motto-translation”> — {era.mottoTranslation}</span>}
        </div>
        <p className="opener-intro">{era.intro}</p>
      </header>

      <div className="chapter-body">
        {groupBlocks(era.blocks).map((row, i) => (
          <div key={i} className={`chapter-row ${row.sidenote ? 'has-sidenote' : ''}`}>
            <div className="chapter-row-main">
              <Block
                block={row.main}
                era={era}
                onSavedPassage={onSavedPassage}
                isSaved={isSaved}
                saveable={saveable}
                onSidenoteClick={onSidenoteClick}
              />
            </div>
            {row.sidenote && (
              <div className="chapter-row-margin">
                <Block
                  block={row.sidenote}
                  era={era}
                  onSavedPassage={onSavedPassage}
                  isSaved={isSaved}
                  saveable={saveable}
                  onSidenoteClick={onSidenoteClick}
                />
              </div>
            )}
          </div>
        ))}
      </div>

      <FurtherPanel era={era} onSave={onSavedPassage} isSaved={isSaved} saveable={saveable} />
      <CarryForward era={era} />
    </article>
  );
}

// =====================================================
// "Read more" / Further reading panel at end of each chapter
// =====================================================
function FurtherPanel({ era, onSave, isSaved, saveable }) {
  const [open, setOpen] = useState(false);
  return (
    <section className={`further-panel ${open ? 'open' : ''}`}>
      <button className="further-toggle" onClick={() => setOpen(!open)}>
        <span className="further-mono">References &amp; further reading</span>
        <span className="further-count">{era.further.length} items</span>
        <span className={`further-chev ${open ? 'rot' : ''}`}>›</span>
      </button>
      {open && (
        <div className="further-list">
          {era.further.map((r, i) => {
            const saved = isSaved && isSaved(r.ref, era.id);
            return (
              <div key={i} className="further-item" draggable={saveable}
                onDragStart={(e) => {
                  e.dataTransfer.effectAllowed = 'copy';
                  e.dataTransfer.setData('text/plain', r.ref);
                  e.dataTransfer.setData('application/x-era-save', JSON.stringify({
                    kind: 'reference', text: r.ref, note: r.note,
                    eraId: era.id, eraTitle: era.title, cite: r.ref
                  }));
                  document.body.classList.add('is-dragging-save');
                }}
                onDragEnd={() => document.body.classList.remove('is-dragging-save')}
              >
                <div className="further-num">{String(i + 1).padStart(2, '0')}</div>
                <div className="further-body">
                  <div className="further-ref">{r.ref}</div>
                  <div className="further-note">{r.note}</div>
                </div>
                {saveable && (
                  <BookmarkButton
                    saved={!!saved}
                    onClick={() => onSave({
                      kind: 'reference', text: r.ref, note: r.note,
                      eraId: era.id, eraTitle: era.title, cite: r.ref
                    })}
                  />
                )}
              </div>
            );
          })}
        </div>
      )}
    </section>
  );
}

function CarryForward({ era }) {
  return (
    <section className="carry-forward">
      <div className="cf-label">Carries forward</div>
      <div className="cf-text">{era.carriesForward}</div>
    </section>
  );
}

// =====================================================
// Top of book: cover + table of contents
// =====================================================
function Cover({ eras, onJump }) {
  return (
    <article className="book-cover">
      <div className="cover-eyebrow">An internal reading</div>
      <h1 className="cover-title">
        How we <em>think about</em> how we work.
      </h1>
      <p className="cover-lede">
        A short book on six eras of organizational philosophy — guild to horizon — and what each one
        carries forward into how we work today. Read it like a book. Save anything you'd like to
        return to. Hover the margin for notes; click them to pin.
      </p>
      <div className="cover-toc">
        <div className="toc-head">Contents</div>
        {eras.map((era, i) => (
          <button key={era.id} className="toc-row" onClick={() => onJump(era.id)}>
            <span className="toc-num">{era.number}</span>
            <span className="toc-title">{era.title}</span>
            <span className="toc-dot"></span>
            <span className="toc-dates">{era.dates}</span>
          </button>
        ))}
      </div>
      <div className="cover-tips">
        <div className="tip">
          <div className="tip-mark">¶</div>
          <div className="tip-text"><b>Highlight any passage</b> and a save button will appear.</div>
        </div>
        <div className="tip">
          <div className="tip-mark">⬚</div>
          <div className="tip-text"><b>Drag a paragraph</b> to the bookmark in the corner to save it.</div>
        </div>
        <div className="tip">
          <div className="tip-mark">⌐</div>
          <div className="tip-text"><b>Click footnote numbers</b> for margin notes and sources.</div>
        </div>
      </div>
    </article>
  );
}

// =====================================================
// Sidenote popover (when user clicks a footnote sup)
// =====================================================
function SidenotePopover({ note, anchor, onClose, onSave, saved, saveable }) {
  if (!note || !anchor) return null;
  const rect = anchor.getBoundingClientRect();
  // Position below + right of anchor; clamp to viewport
  const ww = window.innerWidth;
  const wh = window.innerHeight;
  const w = 360;
  let left = rect.left + 16;
  let top = rect.bottom + 8;
  if (left + w > ww - 16) left = ww - w - 16;
  if (left < 16) left = 16;
  if (top + 220 > wh - 16) top = Math.max(16, rect.top - 220 - 8);

  return (
    <>
      <div className="sidenote-backdrop" onClick={onClose} />
      <div className="sidenote-popover" style={{ left, top, width: w }}>
        <div className="sp-head">
          <span className="sp-label">{note.label || 'Sidenote'}</span>
          <button className="sp-close" onClick={onClose} aria-label="Close">×</button>
        </div>
        <div className="sp-title">{note.title}</div>
        <div className="sp-text">{note.text}</div>
        {note.cite && <div className="sp-cite">{note.cite}</div>}
        {saveable && (
          <div className="sp-foot">
            <button className="sp-save" onClick={() => onSave({
              kind: 'sidenote', text: note.title + ' — ' + note.text,
              cite: note.cite, eraId: note.eraId, eraTitle: note.eraTitle
            })}>
              {saved ? '✓ Saved' : 'Save this note'}
            </button>
          </div>
        )}
      </div>
    </>
  );
}

// =====================================================
// Top bar / book chrome
// =====================================================
function BookChrome({ eras, currentEraId, progress, onJump, onOpenInbox, savedCount, dark }) {
  const [navOpen, setNavOpen] = useState(false);
  return (
    <>
      <header className="book-chrome">
        <div className="bc-left">
          <button className="bc-toc" onClick={() => setNavOpen(!navOpen)} aria-label="Contents">
            <span className="bc-toc-bars"><span/><span/><span/></span>
            <span className="bc-toc-label">Contents</span>
          </button>
        </div>
        <div className="bc-center">
          <div className="bc-brand">
            <span className="bc-mark"></span>
            <span className="bc-title">Eras of Organizational Philosophy</span>
          </div>
          <div className="bc-progress">
            <div className="bc-progress-track">
              <div className="bc-progress-fill" style={{ width: (progress * 100) + '%' }}/>
            </div>
            <div className="bc-progress-label">{Math.round(progress * 100)}%</div>
          </div>
        </div>
        <div className="bc-right">
          <button className="bc-inbox" onClick={onOpenInbox} aria-label="Reading list">
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
              <path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
            </svg>
            <span className="bc-inbox-count">{savedCount}</span>
            <span className="bc-inbox-label">Saved</span>
          </button>
        </div>
      </header>
      {navOpen && (
        <div className="toc-overlay" onClick={() => setNavOpen(false)}>
          <div className="toc-overlay-panel" onClick={(e) => e.stopPropagation()}>
            <div className="toc-overlay-head">Contents</div>
            <button className="toc-overlay-row" onClick={() => { onJump('__cover'); setNavOpen(false); }}>
              <span className="toc-overlay-num">·</span>
              <span className="toc-overlay-title">Cover</span>
            </button>
            {eras.map((era) => (
              <button key={era.id}
                className={`toc-overlay-row ${currentEraId === era.id ? 'active' : ''}`}
                onClick={() => { onJump(era.id); setNavOpen(false); }}>
                <span className="toc-overlay-num">{era.number}</span>
                <span className="toc-overlay-title">{era.title}</span>
                <span className="toc-overlay-dates">{era.dates}</span>
              </button>
            ))}
          </div>
        </div>
      )}
    </>
  );
}

Object.assign(window, {
  eraThemeStyle, EraMotif, Block, ChapterPage, FurtherPanel, CarryForward,
  Cover, SidenotePopover, BookChrome,
});
