/* global React, ReactDOM */
const { useState, useEffect, useMemo } = React;

// Read fresh every render — data.js may swap window.SPREAD_DATA after a live fetch
const getD = () => window.SPREAD_DATA;

// ============ Sparkline ============
function Sparkline({ data, color, width = 60, height = 22 }) {
  const min = Math.min(...data);
  const max = Math.max(...data);
  const range = max - min || 1;
  const step = width / (data.length - 1);
  const pts = data.map((v, i) => `${i * step},${height - ((v - min) / range) * (height - 2) - 1}`).join(' ');
  return (
    <svg className="spark" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none">
      <polyline points={pts} className="chart-line" stroke={color} />
      <circle cx={(data.length - 1) * step} cy={height - ((data[data.length - 1] - min) / range) * (height - 2) - 1} r="1.8" fill={color} />
    </svg>
  );
}

// ============ Lead chart ============
function LeadChart() {
  const data = [55, 55, 56, 55, 56, 56, 56, 57, 58, 60, 60, 61, 62, 62, 62];
  const w = 600, h = 90;
  const max = 65, min = 50;
  const step = w / (data.length - 1);
  const pts = data.map((v, i) => `${i * step},${h - ((v - min) / (max - min)) * (h - 6) - 3}`).join(' ');
  const area = `0,${h} ${pts} ${w},${h}`;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} className="lead-chart" preserveAspectRatio="none" style={{ width: '100%' }}>
      <defs>
        <linearGradient id="leadGrad" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor="var(--accent)" stopOpacity="0.4" />
          <stop offset="100%" stopColor="var(--accent)" stopOpacity="0" />
        </linearGradient>
      </defs>
      {[0, 1, 2, 3].map(i => (
        <line key={i} x1="0" x2={w} y1={i * h / 3} y2={i * h / 3} stroke="#333" strokeDasharray="2 3" strokeWidth="0.5" />
      ))}
      <polygon points={area} fill="url(#leadGrad)" />
      <polyline points={pts} fill="none" stroke="var(--accent)" strokeWidth="2" />
      <circle cx={(data.length - 1) * step} cy={h - ((data[data.length - 1] - min) / (max - min)) * (h - 6) - 3} r="3" fill="var(--accent)" stroke="white" strokeWidth="1" />
    </svg>
  );
}

// ============ Ticker ============
function Ticker() {
  const D = getD();
  const items = [...D.ticker, ...D.ticker]; // duplicate for seamless scroll
  return (
    <div className="ticker">
      <div className="ticker-label"><span className="ticker-pulse" /> LIVE · ON-CHAIN</div>
      <div className="ticker-track">
        {items.map((t, i) => (
          <span key={i} className="ticker-item">
            <span className="sym">{t.sym}</span>
            <span>{t.price}</span>
            <span className={t.dir === 'up' ? 'bid' : 'ask'}>
              {t.dir === 'up' ? '▲' : '▼'} {t.delta}
            </span>
          </span>
        ))}
      </div>
    </div>
  );
}

// ============ Masthead ============
function Masthead() {
  const today = new Date('2026-04-26');
  const dateStr = today.toLocaleDateString('en-US', {
    weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
  }).toUpperCase();
  return (
    <header className="masthead">
      <div className="masthead-top">
        <div className="left">
          <span>VOL. II · NO. 117</span>
          <span>{dateStr}</span>
        </div>
        <div className="right">
          <span>NEW YORK · ON-CHAIN</span>
          <span>$1.50 · FREE ON-CHAIN</span>
        </div>
      </div>
      <h1 className="nameplate">The Spread<span className="dot">.</span>today</h1>
      <div className="tagline">"Polls lie. Wallets don't." — All the markets fit to print.</div>
      <nav className="subnav">
        {window.SPREAD_NAV.map(n => (
          <a key={n.key} href={n.href} className={n.key === 'front' ? 'active' : ''}>{n.label}</a>
        ))}
      </nav>
    </header>
  );
}

// ============ Lead story ============
function Lead({ onOpen }) {
  const D = getD();
  const l = D.lead;
  return (
    <article className="lead">
      <div className="lead-kicker">{l.kicker}</div>
      <h2 className="lead-headline" onClick={() => onOpen({ kicker: l.kicker, headline: l.headline, deck: l.deck, body: l.body, data: l.figure.grid })}>
        {l.headline}
      </h2>
      <p className="lead-deck">{l.deck}</p>
      <div className="lead-byline">
        {l.byline.map((b, i) => <span key={i}>{i === 0 ? <strong>{b}</strong> : b}</span>)}
      </div>

      <div className="lead-figure">
        <div className="lead-figure-stat">{l.figure.label}</div>
        <div className="lead-figure-big">
          {l.figure.big}<span className="delta">{l.figure.delta}</span>
        </div>
        <LeadChart />
        <div className="lead-figure-grid">
          {l.figure.grid.map((g, i) => (
            <div key={i}>
              <div className="lfg-label">{g.label}</div>
              <div className="lfg-val">{g.val}</div>
            </div>
          ))}
        </div>
      </div>

      <div className="lead-body">
        {l.body.map((p, i) => <p key={i}>{p}</p>)}
      </div>
    </article>
  );
}

// ============ Story card ============
function StoryCard({ story, onOpen }) {
  return (
    <article className="story" onClick={() => onOpen(story)}>
      <div className={`story-kicker ${story.kickerType || ''}`}>
        {story.kickerType === 'breaking' && '● '}{story.kicker}
      </div>
      <h3 className="story-headline">{story.headline}</h3>
      <p className="story-deck">{story.deck}</p>
      <div className="story-data">
        {story.data.map((d, i) => {
          const isUp = d.includes('↑');
          const isDown = d.includes('↓');
          return (
            <span key={i} className={isUp ? 'bid' : isDown ? 'ask' : ''}>{d}</span>
          );
        })}
      </div>
    </article>
  );
}

// ============ Whale row ============
function WhaleRow({ whale }) {
  const [open, setOpen] = useState(false);
  return (
    <div className={`whale-row ${open ? 'expanded' : ''}`} onClick={() => setOpen(o => !o)}>
      <div className="whale-top">
        <div className="whale-rank">{whale.rank}</div>
        <div className="whale-main">
          <h4 className="whale-name">{whale.name}</h4>
          <div className="whale-addr mono">{whale.addr.slice(0, 18)}…{whale.addr.slice(-6)}</div>
        </div>
        <div className={`whale-amt ${whale.amtType}`}>{whale.amt}</div>
      </div>
      <div className="whale-meta">
        <span>{whale.market}</span>
        <span>·</span>
        <span>{whale.time}</span>
        <span style={{ marginLeft: 'auto' }}>{open ? '− COLLAPSE' : '+ EXPAND'}</span>
      </div>
      {open && (
        <div className="whale-detail">
          {whale.detail}
          <div className="whale-detail-grid">
            {whale.grid.map((g, i) => (
              <div key={i} className="wdg-item">
                <span className="label">{g.label}</span>
                <span className="val">{g.val}</span>
              </div>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}

// ============ Movers table ============
function Movers() {
  const D = getD();
  return (
    <table className="movers-table">
      <thead>
        <tr><th>Market</th><th>Trend</th><th style={{ textAlign: 'right' }}>Price</th><th style={{ textAlign: 'right' }}>Δ</th></tr>
      </thead>
      <tbody>
        {D.movers.map((m, i) => (
          <tr key={i}>
            <td><div className="name">{m.name}</div></td>
            <td><Sparkline data={m.spark} color={m.dir === 'up' ? 'var(--bid)' : 'var(--ask)'} /></td>
            <td className="price">{m.price}</td>
            <td className={`delta ${m.dir === 'up' ? 'bid' : 'ask'}`}>{m.dir === 'up' ? '▲' : '▼'} {m.delta}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

// ============ Feed ============
function Feed() {
  const D = getD();
  return (
    <div className="feed">
      {D.feed.map((f, i) => (
        <div key={i} className="feed-item">
          <div className={`feed-time ${f.live ? 'live' : ''}`}>{f.live ? <span className="live">● {f.time}</span> : f.time}</div>
          <div className="feed-body">
            <div className="feed-headline">{f.headline}</div>
            <div className="feed-data">{f.data}</div>
          </div>
        </div>
      ))}
    </div>
  );
}

// ============ Pull quote ============
function PullQuote() {
  const D = getD();
  return (
    <div className="pull-quote">
      <div className="pull-quote-mark">"</div>
      <div className="pull-quote-text">{D.pullQuote.text}</div>
      <div className="pull-quote-attr">
        <strong>— {D.pullQuote.attr[0]}</strong>
        <span>{D.pullQuote.attr[1]}</span>
      </div>
    </div>
  );
}

// ============ Entities ============
function Entities() {
  const D = getD();
  return (
    <div>
      {D.entities.map((e, i) => (
        <div key={i} className="entity">
          <div className="entity-stamp">{e.stamp}</div>
          <h4 className="entity-name">{e.name}</h4>
          <div className="entity-aka">{e.aka.split('→').map((p, j, arr) => (
            <span key={j}>{p}{j < arr.length - 1 && <span className="arrow"> → </span>}</span>
          ))}</div>
          <div className="entity-summary">{e.summary}</div>
          <div className="entity-stats">
            {e.stats.map((s, j) => (
              <React.Fragment key={j}>
                <div className="label">{s.label}</div>
                <div className="val">{s.val}</div>
              </React.Fragment>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

// ============ Op-ed ============
function OpEd() {
  const D = getD();
  const o = D.opEd;
  return (
    <div className="oped">
      <div className="oped-stamp">{o.stamp}</div>
      <h3 className="oped-headline">{o.headline}</h3>
      <div className="oped-author">
        <div className="oped-avatar">{o.author.initials}</div>
        <div className="oped-author-name">
          <strong>{o.author.name}</strong>
          <span>{o.author.role}</span>
        </div>
      </div>
      <div className="oped-body">
        {o.body.map((p, i) => <p key={i}>{p}</p>)}
      </div>
    </div>
  );
}

// ============ Modal ============
function StoryModal({ story, onClose }) {
  if (!story) return null;
  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}>CLOSE ✕</button>
        <div className="modal-kicker">{story.kicker}</div>
        <h2 className="modal-headline">{story.headline}</h2>
        <p className="modal-deck">{story.deck}</p>
        <div className="modal-body">
          {(story.body || [
            "The trade hit the tape at " + (story.data?.[0] || "the open") + ". Within minutes, the book repriced. Within an hour, a second wallet — funded from the same Coinbase Prime sub-account — joined the position.",
            "On-chain analysis by The Spread links the activity to a single beneficial owner. The same cluster has been active in three other markets this week.",
            "We've reached out for comment. They have not responded. They never do."
          ]).map((p, i) => <p key={i}>{p}</p>)}
        </div>
        {story.data && Array.isArray(story.data) && typeof story.data[0] === 'string' && (
          <div className="modal-data">
            {story.data.map((d, i) => (
              <div key={i} className="item">
                <span className="val">{d}</span>
              </div>
            ))}
          </div>
        )}
        {story.data && Array.isArray(story.data) && typeof story.data[0] === 'object' && (
          <div className="modal-data">
            {story.data.map((d, i) => (
              <div key={i} className="item">
                <span className="label">{d.label}</span>
                <span className="val">{d.val}</span>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ============ Tweaks ============
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "bid",
  "showTicker": true,
  "showWhales": true,
  "density": "comfortable"
}/*EDITMODE-END*/;

function App() {
  const D = getD();
  const [tweaks, setTweak] = window.useTweaks(TWEAK_DEFAULTS);
  const [openStory, setOpenStory] = useState(null);

  // Apply accent
  useEffect(() => {
    const root = document.documentElement;
    root.style.setProperty('--accent', tweaks.accent === 'ask' ? 'var(--ask)' : 'var(--bid)');
    root.style.setProperty('--accent-soft', tweaks.accent === 'ask' ? 'rgba(208, 69, 69, 0.08)' : 'rgba(34, 160, 107, 0.08)');
  }, [tweaks.accent]);

  // Esc closes modal
  useEffect(() => {
    const fn = e => { if (e.key === 'Escape') setOpenStory(null); };
    window.addEventListener('keydown', fn);
    return () => window.removeEventListener('keydown', fn);
  }, []);

  const TP = window.TweaksPanel;
  const TR = window.TweakRadio;
  const TT = window.TweakToggle;
  const TS = window.TweakSection;

  return (
    <>
      {tweaks.showTicker && <Ticker />}
      <Masthead />
      <div className="page">
        <div className="main-grid">
          {/* LEFT COLUMN — Whale Watch */}
          <aside className="col col-left">
            <div className="section-kicker">
              <span>Whale Watch</span>
              <span className="meta">TOP 6 · 24H</span>
            </div>
            {tweaks.showWhales && (
              <div className="whale-board">
                {D.whales.map(w => <WhaleRow key={w.rank} whale={w} />)}
              </div>
            )}

            <div className="section-kicker">
              <span>Entities Revealed</span>
              <span className="meta">VERIFIED</span>
            </div>
            <Entities />
          </aside>

          {/* MIDDLE COLUMN — Lead + stories */}
          <main className="col col-mid">
            <Lead onOpen={setOpenStory} />
            <PullQuote />
            <div className="section-kicker" style={{ marginTop: 0 }}>
              <span>Front Page</span>
              <span className="meta">11 STORIES · UPDATED 2 MIN AGO</span>
            </div>
            <div className="stories-grid">
              {D.stories.map((s, i) => (
                <StoryCard key={i} story={s} onOpen={setOpenStory} />
              ))}
            </div>
          </main>

          {/* RIGHT COLUMN — Movers + Feed + Op-ed */}
          <aside className="col col-right">
            <div className="section-kicker">
              <span>Market Movers</span>
              <span className="meta">24H</span>
            </div>
            <Movers />

            <div className="section-kicker" style={{ marginTop: 24 }}>
              <span>Breaking</span>
              <span className="meta">LIVE FEED</span>
            </div>
            <Feed />

            <OpEd />
          </aside>
        </div>

        <footer className="footer">
          <div className="nameplate-sm">The Spread<span style={{ color: 'var(--ask)' }}>.</span>today</div>
          <div>© 2026 · BUILT ON-CHAIN · NOT INVESTMENT ADVICE · NEVER WAS · NEVER WILL BE</div>
          <div>RSS · API · TELEGRAM · X</div>
        </footer>
      </div>

      {openStory && <StoryModal story={openStory} onClose={() => setOpenStory(null)} />}

      {TP && (
        <TP title="Tweaks">
          <TS title="Accent">
            <TR
              label="Bid green vs Ask red dominant"
              value={tweaks.accent}
              onChange={v => setTweak('accent', v)}
              options={[
                { value: 'bid', label: 'BID · GREEN' },
                { value: 'ask', label: 'ASK · RED' }
              ]}
            />
          </TS>
          <TS title="Layout">
            <TT label="Show ticker" value={tweaks.showTicker} onChange={v => setTweak('showTicker', v)} />
            <TT label="Show whale watch" value={tweaks.showWhales} onChange={v => setTweak('showWhales', v)} />
          </TS>
        </TP>
      )}
    </>
  );
}

// Initial mount + re-mount when live data arrives from data.js
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
window.addEventListener('spread-data-loaded', () => root.render(<App />));
