/* eslint-disable */
// journal.jsx — Field Notes index, Block (light mode) edition.
// Cream paper, carbon ink, magenta + indigo accents. Editorial list layout
// mirroring the MaisonJournal field-notes treatment.
//
// Data:
//   - window.JOURNAL — static fallback list (cat / title / read / date)
//   - window.Store.getArticles() — admin-published articles via content-store
//   The two are merged: admin entries first, fallback list filling in if empty.
//
// Articles link to article.html?id=<slug>.

// ── Palette + tokens ────────────────────────────────────────────
const J_PALETTE = (typeof window !== 'undefined' && window.PALETTE) || {
  ivory:   '#efeae0',
  ivory2:  '#efeae0',
  carbon:  '#221a1d',
  merlot:  '#6b1a35',
  magenta: '#bc2a4e',
  lilac:   '#c5a4be',
  indigo:  '#27557e',
  sage:    '#6fa57c',
};

const J_FONTS = {
  // Field Notes runs a Fraunces-led type system instead of Fraunces.
  // Hero uses Light (300); secondary headings here use Regular (400) since
  // they're at smaller sizes where Light would feel underweight.
  display: "'Fraunces', Georgia, serif",
  body:    "'Montserrat', system-ui, sans-serif",
  script:  "'Homemade Apple', cursive",
  mono:    "'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace",
};

const J_RULE = 'rgba(34,26,29,.18)';

// ── Helpers ─────────────────────────────────────────────────────
function jSlug(s) {
  if (typeof window !== 'undefined' && typeof window.slugify === 'function') {
    return window.slugify(s);
  }
  return (s || '').toString().toLowerCase()
    .replace(/['’‘]/g, '')
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');
}

function readTimeFor(a) {
  if (a.read) return a.read;
  if (a.kicker && /\d+\s*min/i.test(a.kicker)) {
    const m = a.kicker.match(/(\d+\s*min[^·]*)/i);
    if (m) return m[1].trim();
  }
  // Approximate from body / dek when no explicit read time is set.
  const text = (a.body || a.dek || '').toString();
  if (!text) return '— min';
  const words = text.split(/\s+/).filter(Boolean).length;
  const mins = Math.max(1, Math.round(words / 220));
  return `${mins} min`;
}

function categoryFor(a) {
  if (a.cat) return a.cat;
  const map = {
    'main-character': 'Main Character',
    'playbook':       'Playbook',
    'scroll-culture': 'Scroll Culture',
    'reading-room':   'Reading Room',
    'bulletin':       'Bulletin',
  };
  return map[a.contentType] || 'Essay';
}

// Reusable mono caption.
const MONO_CAP = {
  fontFamily: J_FONTS.mono,
  fontSize: 11,
  letterSpacing: '.22em',
  textTransform: 'uppercase',
};

// ── Page hero ───────────────────────────────────────────────────
function JournalHero({ accent }) {
  const Split = (typeof window !== 'undefined' && window.SplitText) ? window.SplitText : null;
  return (
    <section style={{
      padding: '120px 32px 80px',
      borderBottom: `1px solid ${J_RULE}`,
    }}>
      <Reveal>
        <div style={{ ...MONO_CAP, color: 'rgba(34,26,29,.55)', marginBottom: 28 }}>
          [ Field Notes &middot; 02 ]
        </div>
      </Reveal>
      <Reveal delay={80}>
        <h1 style={{
          fontFamily: "'Fraunces', Georgia, serif",
          fontWeight: 300,
          fontStyle: 'normal',
          fontSize: 'clamp(56px, 11vw, 200px)',
          lineHeight: .92,
          letterSpacing: '-.025em',
          margin: 0,
          color: J_PALETTE.carbon,
          whiteSpace: 'nowrap',
        }}>
          {Split ? (
            <Split text="Field" style={{ display: 'inline-block' }} />
          ) : (
            'Field'
          )}
          {' '}
          <span style={{
            fontFamily: "'Homemade Apple', cursive",
            color: accent,
            fontWeight: 400,
            fontSize: '.78em',
            display: 'inline-block',
            transform: 'rotate(-3deg) translateY(.05em)',
            letterSpacing: 0,
            marginLeft: '.04em',
          }}>notes.</span>
        </h1>
      </Reveal>
    </section>
  );
}

// ── Editor's Letter ─────────────────────────────────────────────
// Default opening content for the Field Notes page. Always renders, whether
// or not admin-published articles exist. Editable via the admin KV note at
// window.Store.getEditorNote(); fields default to studio copy when missing.
const EDITOR_NOTE_DEFAULTS = {
  kicker:   'From the Editor',
  title:    'A note before the first chapter.',
  body:     "Welcome to The Field Notes — a quiet shelf where Chapter 1's thinking gets written down between the work. Essays, observations, recommendations, occasional confessions. New entries arrive as they arrive; we don't publish on a schedule. Until then, this letter holds the door open.",
  flourish: 'Stay curious.',
  signoff:  '— The Studio',
};

function EditorsLetter({ accent }) {
  const stored = (typeof window !== 'undefined' && window.Store && typeof window.Store.getEditorNote === 'function')
    ? (window.Store.getEditorNote() || {})
    : {};
  const note = {
    kicker:   stored.kicker   || EDITOR_NOTE_DEFAULTS.kicker,
    title:    stored.title    || EDITOR_NOTE_DEFAULTS.title,
    body:     stored.body     || EDITOR_NOTE_DEFAULTS.body,
    flourish: ('flourish' in stored) ? stored.flourish : EDITOR_NOTE_DEFAULTS.flourish,
    signoff:  stored.signoff  || EDITOR_NOTE_DEFAULTS.signoff,
  };

  // Split the body on blank lines so editors can write multi-paragraph notes
  // and get proper spacing without inline HTML.
  const paragraphs = (note.body || '')
    .split(/\n{2,}/)
    .map((p) => p.trim())
    .filter(Boolean);

  return (
    <section style={{
      background: J_PALETTE.ivory,
      padding: '120px 32px',
      borderBottom: `1px solid ${J_RULE}`,
    }}>
      <div style={{
        maxWidth: 720,
        margin: '0 auto',
        textAlign: 'center',
      }}>
        <Reveal>
          <div style={{
            ...MONO_CAP,
            fontSize: 11,
            letterSpacing: '.24em',
            color: 'rgba(34,26,29,.55)',
            marginBottom: 28,
          }}>
            {note.kicker}
          </div>
        </Reveal>

        <Reveal delay={80}>
          <h2 style={{
            fontFamily: J_FONTS.display,
            fontWeight: 400,
            fontSize: 'clamp(36px, 5vw, 72px)',
            lineHeight: 1.05,
            letterSpacing: '-.03em',
            color: J_PALETTE.carbon,
            margin: '0 auto',
            maxWidth: '28ch',
            textWrap: 'balance',
          }}>
            {note.title}
          </h2>
        </Reveal>

        <Reveal delay={160}>
          <div style={{
            marginTop: 48,
            maxWidth: '56ch',
            marginLeft: 'auto',
            marginRight: 'auto',
            textAlign: 'left',
          }}>
            {paragraphs.map((p, i) => (
              <p key={i} style={{
                fontFamily: J_FONTS.body,
                fontSize: 18,
                lineHeight: 1.65,
                color: J_PALETTE.carbon,
                margin: i === 0 ? 0 : '1.4em 0 0',
              }}>
                {p}
              </p>
            ))}
          </div>
        </Reveal>

        {note.flourish ? (
          <Reveal delay={220}>
            <div style={{
              fontFamily: J_FONTS.script,
              color: accent,
              fontSize: 42,
              lineHeight: 1,
              transform: 'rotate(-2deg)',
              display: 'inline-block',
              marginTop: 24,
            }}>
              {note.flourish}
            </div>
          </Reveal>
        ) : null}

        <Reveal delay={260}>
          <div style={{
            ...MONO_CAP,
            fontSize: 10,
            letterSpacing: '.22em',
            color: 'rgba(34,26,29,.55)',
            marginTop: 32,
          }}>
            {note.signoff}
          </div>
        </Reveal>
      </div>
    </section>
  );
}

// ── Article row ─────────────────────────────────────────────────
function JournalRow({ entry, accent }) {
  const href  = `article.html?id=${entry.id || jSlug(entry.title || '')}`;
  const cat   = categoryFor(entry);
  const date  = entry.date || '';
  const title = (entry.title || '').replace(/\.$/, '');
  const read  = readTimeFor(entry);

  // State-driven hover lets title + arrow shift together without a per-row
  // <style> tag.
  const [hover, setHover] = React.useState(false);

  return (
    <a
      href={href}
      data-cursor="Read"
      onMouseEnter={() => setHover(true)}
      onMouseLeave={() => setHover(false)}
      onFocus={() => setHover(true)}
      onBlur={() => setHover(false)}
      style={{ display: 'block', textDecoration: 'none', color: 'inherit', cursor: 'none' }}
    >
      <article style={{
        display: 'grid',
        gridTemplateColumns: '140px 120px 1fr 100px 40px',
        alignItems: 'center', gap: 30,
        padding: '36px 0',
        borderBottom: `1px solid ${J_RULE}`,
        transition: 'background .25s ease',
        background: hover ? 'rgba(34,26,29,.02)' : 'transparent',
      }}>
        <span style={{
          ...MONO_CAP,
          color: accent,
          fontSize: 10,
        }}>{cat}</span>

        <span style={{
          ...MONO_CAP,
          color: 'rgba(34,26,29,.55)',
          fontSize: 10,
        }}>{date}</span>

        <h3 style={{
          fontFamily: J_FONTS.display,
          fontWeight: 400,
          fontSize: 'clamp(24px, 3vw, 44px)',
          lineHeight: 1.06,
          letterSpacing: '-.025em',
          margin: 0,
          color: hover ? accent : J_PALETTE.carbon,
          transition: 'color .25s ease',
          textWrap: 'balance',
        }}>{title}</h3>

        <span style={{
          ...MONO_CAP,
          color: 'rgba(34,26,29,.55)',
          fontSize: 10,
        }}>{read}</span>

        <span style={{
          textAlign: 'right',
          color: accent,
          fontSize: 22,
          display: 'inline-block',
          transform: hover ? 'translateX(6px)' : 'translateX(0)',
          transition: 'transform .25s ease',
        }}>→</span>
      </article>
    </a>
  );
}

// ── List ────────────────────────────────────────────────────────
function JournalList({ entries, accent }) {
  // No empty state — the EditorsLetter section above always carries the page.
  if (!entries.length) return null;

  return (
    <section style={{ padding: '40px 32px 120px' }}>
      <Reveal>
        <div style={{
          display: 'grid',
          gridTemplateColumns: '140px 120px 1fr 100px 40px',
          gap: 30,
          paddingBottom: 14,
          borderBottom: `1px solid ${J_RULE}`,
          ...MONO_CAP,
          fontSize: 10,
          color: 'rgba(34,26,29,.45)',
        }}>
          <span>Category</span>
          <span>Date</span>
          <span>Title</span>
          <span>Read</span>
          <span></span>
        </div>
      </Reveal>
      <div>
        {entries.map((e, i) => (
          <Reveal key={(e.id || e.title || '') + i} delay={i * 50}>
            <JournalRow entry={e} accent={accent} />
          </Reveal>
        ))}
      </div>
    </section>
  );
}

// ── Page composer ───────────────────────────────────────────────
function JournalPage({ tweaks }) {
  const accent  = (tweaks && tweaks.accent)  || J_PALETTE.magenta;
  const accent2 = (tweaks && tweaks.accent2) || J_PALETTE.indigo;

  // Subscribe to the content store so admin-published articles appear without
  // a hard refresh. Falls back to window.JOURNAL when the store is empty.
  const [, force] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => {
    if (typeof window === 'undefined' || !window.Store) return;
    const unsub = window.Store.subscribe && window.Store.subscribe(() => force());
    return () => { if (typeof unsub === 'function') unsub(); };
  }, []);

  // Page-level CSS vars so any shared :hover / cursor styles inherit tone.
  React.useEffect(() => {
    if (typeof document === 'undefined') return;
    const root = document.documentElement;
    root.style.setProperty('--accent', accent);
    root.style.setProperty('--accent2', accent2);
    root.style.setProperty('--ink', J_PALETTE.carbon);
    root.style.setProperty('--paper', J_PALETTE.ivory);
    root.style.setProperty('--muted', 'rgba(34,26,29,.55)');
    root.style.setProperty('--rule', J_RULE);
    document.body.style.background = J_PALETTE.ivory;
    document.body.style.color      = J_PALETTE.carbon;
  }, [accent, accent2]);

  // Merge sources: admin articles first → row entries; fallback to JOURNAL.
  const entries = React.useMemo(() => {
    const fromStore = (typeof window !== 'undefined' && window.Store && window.Store.getArticles)
      ? window.Store.getArticles()
      : [];
    const fromGlobal = (typeof window !== 'undefined' && Array.isArray(window.JOURNAL))
      ? window.JOURNAL
      : [];
    const list = fromStore.length ? fromStore : fromGlobal;
    return list.map((a) => ({
      ...a,
      title: a.title || 'Untitled',
      cat:   categoryFor(a),
      date:  a.date || '',
      read:  readTimeFor(a),
    }));
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    (typeof window !== 'undefined' && window.Store && window.Store.getArticles)
      ? window.Store.getArticles().length : 0,
  ]);

  return (
    <div style={{
      minHeight: '100vh',
      background: J_PALETTE.ivory,
      color: J_PALETTE.carbon,
      fontFamily: J_FONTS.body,
    }}>
      <BlockNav activePage="journal" />
      <JournalHero accent={accent} />
      <EditorsLetter accent={accent} />
      <JournalList entries={entries} accent={accent} />
      <SiteFooter />
    </div>
  );
}

Object.assign(window, { JournalPage });
