/* global React, useApi, useMeta, useInfiniteList, LiveMarketCard, LiveMarketGrid, LivePill, Loading, LoadingBar, ApiError, Tag, NextResolutionWidget, SearchInput, ConditionsBuilder, serializeConditions, formatMoney */

// =========================================================================
// HOME — Active markets, live data only, category-filterable.
// =========================================================================
function HomePage({ navigate }) {
  const { categories, models } = useMeta();
  const [catFilter, setCatFilter] = React.useState('all');
  // resolved filter: 'open' (default), 'true' (resolved only), 'all'
  const [resolvedFilter, setResolvedFilter] = React.useState('open');
  // Disagreement: when true, only markets where models split YES vs NO.
  const [disagreementOnly, setDisagreementOnly] = React.useState(false);
  // Multi-model conditions: { [modelId]: 'YES'|'NO'|'right'|'wrong' }
  const [conditions, setConditions] = React.useState({});
  // Search — `searchInput` is what's in the box, `q` is debounced for the API.
  const [searchInput, setSearchInput] = React.useState('');
  const [q, setQ] = React.useState('');

  // Pull more top picks than we need so randomisation has variety to draw from.
  const topPicks = useApi(() => window.CloudLayerAPI.listTopPicks(24), []);
  // Tab counts mirror every active filter — search, disagreement, conditions.
  const conditionsStrForCats = serializeConditions(conditions);
  const cats = useApi(
    () => window.CloudLayerAPI.listCategories({
      q,
      disagreement: disagreementOnly ? 'true' : '',
      conditions: conditionsStrForCats,
    }),
    [q, disagreementOnly, conditionsStrForCats],
  );

  // Infinite-scroll the market grid. Pages of 24, append on bottom-sentinel.
  // Resets whenever category, resolved filter, or search query changes.
  const PAGE_SIZE = 24;
  const conditionsStr = serializeConditions(conditions);
  const markets = useInfiniteList(
    (offset, limit) =>
      window.CloudLayerAPI.listMarkets({
        category: catFilter === 'all' ? '' : catFilter,
        resolved: resolvedFilter,
        disagreement: disagreementOnly ? 'true' : '',
        conditions: conditionsStr,
        q,
        limit,
        offset,
      }),
    [catFilter, resolvedFilter, disagreementOnly, conditionsStr, q],
    PAGE_SIZE,
  );

  // Quietly refresh the first page every 60s so prices / verdicts stay live.
  // We don't refresh later pages — that would jump the user back to the top.
  React.useEffect(() => {
    const t = setInterval(markets.refresh, 60_000);
    return () => clearInterval(t);
  }, [markets.refresh]);

  // Headline pick — pick a random one from the top 12 by volume on every
  // page mount. Seed via a useMemo so it stays stable while the user is on
  // the page (avoids the headline flicker-changing during their visit), but
  // a manual refresh picks a fresh one.
  const headlinePick = React.useMemo(() => {
    const items = topPicks.data?.items || [];
    if (!items.length) return null;
    const pool = items.slice(0, 12);
    return pool[Math.floor(Math.random() * pool.length)];
  }, [topPicks.data]);

  // For the headline we want the strongest model voice on this market — pick
  // the per-model prediction whose edge magnitude is largest. Fall back to
  // the consensus (and label it accordingly) if no per-model data is on file.
  const headlineModel = React.useMemo(() => {
    if (!headlinePick) return null;
    const per = headlinePick.perModel || [];
    if (!per.length) return null;
    const sorted = per.slice().sort((a, b) => {
      const ae = Math.abs((a.yesProbability ?? 0.5) - (headlinePick.yesPrice ?? 0.5));
      const be = Math.abs((b.yesProbability ?? 0.5) - (headlinePick.yesPrice ?? 0.5));
      return be - ae;
    });
    return sorted[0];
  }, [headlinePick]);

  // Count per category depends on the active resolved filter.
  function countFor(c) {
    if (resolvedFilter === 'true') return c.resolvedMarkets || 0;
    if (resolvedFilter === 'all') return (c.markets || 0) + (c.resolvedMarkets || 0);
    return c.markets || 0;
  }
  const totalMarkets = (cats.data?.items || []).reduce((s, c) => s + countFor(c), 0);
  const totalVolume  = (cats.data?.items || []).reduce((s, c) => s + (c.volume  || 0), 0);

  return (
    <div data-screen-label="01 Home">
      {/* HERO — live headline */}
      <section className="hero hero-compact">
        <div className="container">
          <div className="crumb" style={{ marginBottom: 14 }}>
            Live · polled from Polymarket every 2 min · {totalMarkets} markets tracked
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1fr) 360px', gap: 56, alignItems: 'flex-end' }}>
            {headlinePick ? (() => {
              const m = headlineModel;
              const speakerLabel = m
                ? (models.find((x) => x.id === m.modelId)?.label || m.modelLabel || m.modelId)
                : 'The consensus';
              const speakerColor = m
                ? (models.find((x) => x.id === m.modelId)?.color || '#d4ae5a')
                : 'var(--accent)';
              const verdict = m?.verdict || headlinePick.verdict;
              const probPct = Math.round((m?.yesProbability ?? headlinePick.yesProbability) * 100);
              return (
                <h1 style={{ fontSize: 56, lineHeight: 1.04, margin: 0, fontWeight: 300, letterSpacing: '-0.025em', maxWidth: 900 }}>
                  <span style={{ color: speakerColor }}>{speakerLabel}</span> says{' '}
                  <em style={{ fontStyle: 'italic', color: verdict === 'YES' ? 'var(--pos)' : 'var(--neg)' }}>
                    {verdict}
                  </em>{' '}
                  on{' '}
                  <span
                    style={{ fontFamily: 'var(--ff-display)', fontStyle: 'italic', color: 'var(--accent)', cursor: 'pointer' }}
                    onClick={() => navigate('market', { id: headlinePick.polymarketId })}
                  >
                    {(headlinePick.question || '').replace(/\?$/, '')}
                  </span>
                  <span className="mono" style={{ fontSize: 28, marginLeft: 12, color: 'var(--fg-faint)' }}>
                    · {probPct}%
                  </span>
                </h1>
              );
            })() : (
              <h1 style={{ fontSize: 56, lineHeight: 1.04, margin: 0, fontWeight: 300, letterSpacing: '-0.025em' }}>
                Real-time forecasting <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>benchmark</em>.
              </h1>
            )}
            <div style={{ display: 'flex', gap: 32, alignItems: 'flex-end', paddingBottom: 8 }}>
              <div>
                <div className="uppercase faint" style={{ marginBottom: 6 }}>Tracked volume</div>
                <div className="mono tnum" style={{ fontSize: 32, color: 'var(--fg)', fontWeight: 400, lineHeight: 1 }}>
                  {formatMoney(totalVolume)}
                </div>
              </div>
              <div style={{ marginLeft: 'auto' }}>
                <button className="btn btn-accent" onClick={() => navigate('toppicks')}>Top picks →</button>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* NEXT RESOLUTION — live countdown to the next market settling */}
      <section className="container" style={{ padding: '32px 32px 0' }}>
        <NextResolutionWidget navigate={navigate} />
      </section>

      {/* CATEGORY STRIP — live counts */}
      <section className="container" style={{ padding: '56px 32px 0' }}>
        <div className="between" style={{ marginBottom: 18 }}>
          <h2 style={{ fontFamily: 'var(--ff-display)', fontWeight: 300, fontSize: 32, letterSpacing: '-0.02em', margin: 0 }}>
            Across{' '}
            <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>{categories.length} categories</em>
          </h2>
          <LivePill>{cats.loading ? 'loading…' : 'live'}</LivePill>
        </div>

        {cats.error ? (
          <ApiError error={cats.error} hint="Backend offline or DB unreachable." />
        ) : (
          <div className="cat-grid" style={{ gridTemplateColumns: `repeat(${Math.max(1, (cats.data?.items || []).length)}, 1fr)` }}>
            {(cats.data?.items || []).map((c) => {
              const L = c.leader;
              const pct = L
                ? (L.basis === 'accuracy' ? L.accuracy : L.marketAgreement)
                : null;
              return (
                <button
                  key={c.slug}
                  className="cat-card"
                  onClick={() => navigate('category', { slug: c.slug })}
                  style={{ border: 0, background: 'var(--bg)', cursor: 'pointer', textAlign: 'left' }}
                >
                  <div>
                    <div className="cat-name">{c.name}</div>
                    <div className="cat-meta">
                      {c.markets} active{c.resolvedMarkets > 0 ? ` · ${c.resolvedMarkets} resolved` : ''} · {formatMoney(c.volume)}
                    </div>
                  </div>
                  {L ? (
                    <div style={{ marginTop: 14 }}>
                      <div className="uppercase faint" style={{ fontSize: 9.5, letterSpacing: '0.12em', marginBottom: 4 }}>
                        {L.basis === 'accuracy' ? 'Leading · resolved' : 'Leading · agreement'}
                      </div>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 7 }}>
                        <span style={{ width: 8, height: 8, borderRadius: '50%', background: L.color }} />
                        <span style={{ fontFamily: 'var(--ff-display)', fontSize: 17, fontWeight: 400, color: 'var(--fg)' }}>
                          {L.short || L.modelLabel}
                        </span>
                        <span className="mono tnum" style={{ fontSize: 14, color: L.color, marginLeft: 'auto' }}>
                          {Math.round(pct * 100)}%
                        </span>
                      </div>
                      <div className="mono faint" style={{ fontSize: 10.5, marginTop: 4 }}>
                        {L.basis === 'accuracy'
                          ? `${Math.round(L.accuracy * L.resolvedCount)}/${L.resolvedCount} calls right`
                          : `${L.predictions} predictions · awaiting resolutions`}
                      </div>
                    </div>
                  ) : (
                    <div className="dim" style={{ fontSize: 12.5, marginTop: 14, lineHeight: 1.5 }}>{c.blurb}</div>
                  )}
                </button>
              );
            })}
          </div>
        )}
      </section>

      {/* ACTIVE MARKETS GRID — category-filterable */}
      <section className="container" style={{ padding: '64px 32px 0' }}>
        <div className="between" style={{ marginBottom: 18 }}>
          <div>
            <h2 style={{ fontFamily: 'var(--ff-display)', fontWeight: 300, fontSize: 32, letterSpacing: '-0.02em', margin: 0 }}>
              {resolvedFilter === 'true' ? <>Resolved <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>markets</em></>
                : resolvedFilter === 'all' ? <>All <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>markets</em></>
                : <>Active <em style={{ fontStyle: 'italic', color: 'var(--accent)' }}>markets</em></>}
            </h2>
            <div className="dim" style={{ fontSize: 13, marginTop: 6 }}>
              {resolvedFilter === 'true'
                ? 'Settled markets, newest first. Each card shows the outcome and how each model called it.'
                : 'Each card shows the market price, our 6-model consensus, and each model\'s verdict.'}
            </div>
          </div>
          <div className="row gap-12">
            <SearchInput
              value={searchInput}
              onChange={setSearchInput}
              onCommit={setQ}
              placeholder="Search markets…"
            />
            <div className="filter-row">
              <button className={`fchip ${resolvedFilter === 'open' ? 'active' : ''}`} onClick={() => setResolvedFilter('open')}>Open</button>
              <button className={`fchip ${resolvedFilter === 'true' ? 'active' : ''}`} onClick={() => setResolvedFilter('true')}>Resolved</button>
              <button className={`fchip ${resolvedFilter === 'all' ? 'active' : ''}`} onClick={() => setResolvedFilter('all')}>All</button>
              <button
                className={`fchip ${disagreementOnly ? 'active' : ''}`}
                onClick={() => setDisagreementOnly((v) => !v)}
                title="Markets where models split YES vs NO"
              >
                ⚡ Disagree
              </button>
              <ConditionsBuilder
                value={conditions}
                onChange={setConditions}
                modelsList={models}
              />
            </div>
            <span className="mono faint" style={{ fontSize: 11 }}>
              {markets.total != null && markets.total > markets.items.length
                ? <>{markets.items.length} <span style={{ opacity: 0.6 }}>of</span> {markets.total} markets</>
                : <>{markets.total ?? markets.items.length} {(markets.total ?? markets.items.length) === 1 ? 'market' : 'markets'}</>}
            </span>
          </div>
        </div>

        <div className="cat-tabs" style={{ marginBottom: 24 }}>
          <button
            className={`cat-tab ${catFilter === 'all' ? 'active' : ''}`}
            onClick={() => setCatFilter('all')}
          >
            All
            <span className="cat-tab-count">{totalMarkets}</span>
          </button>
          {(cats.data?.items || []).map((c) => (
            <button
              key={c.slug}
              className={`cat-tab ${catFilter === c.slug ? 'active' : ''}`}
              onClick={() => setCatFilter(c.slug)}
            >
              {c.name}
              <span className="cat-tab-count">{countFor(c)}</span>
            </button>
          ))}
        </div>

        {markets.error ? (
          <ApiError error={markets.error} />
        ) : markets.loading && markets.items.length === 0 ? (
          <Loading label="Loading markets…" height={300} />
        ) : markets.items.length === 0 ? (
          <div className="panel" style={{ padding: 28, textAlign: 'center' }}>
            <div className="dim">
              {q
                ? <>No markets match <em style={{ color: 'var(--fg)' }}>"{q}"</em>{catFilter !== 'all' ? ` in ${catFilter}` : ''}.</>
                : disagreementOnly
                ? 'No model disagreements right now — every market with predictions has the models lining up on the same side.'
                : 'No markets in this category yet.'}
            </div>
          </div>
        ) : (
          <>
            {/* Soft loading bar shown ONLY when we're refetching with existing
                items on screen — keeps the grid visible instead of blanking. */}
            {markets.loading && <LoadingBar />}

            <div
              className="mgrid"
              style={{
                opacity: markets.loading ? 0.45 : 1,
                transition: 'opacity 180ms ease',
                pointerEvents: markets.loading ? 'none' : 'auto',
              }}
            >
              {markets.items.map((m) => (
                <LiveMarketCard key={m.polymarketId} market={m} navigate={navigate} />
              ))}
            </div>

            {/* Sentinel — invisible. Triggers next page load when it scrolls
                into view. Stays silent while more is coming; shows a small
                end-of-list line only when we've genuinely run out. */}
            <div
              ref={markets.sentinelRef}
              aria-hidden={markets.hasMore ? 'true' : undefined}
              style={{
                marginTop: 24,
                padding: markets.hasMore ? '8px 0' : '32px 0',
                textAlign: 'center',
                minHeight: markets.hasMore ? 8 : 40,
              }}
            >
              {!markets.hasMore && markets.items.length > 0 && (
                <span className="mono faint" style={{ fontSize: 11, opacity: 0.5 }}>
                  end of list · {markets.items.length} markets
                </span>
              )}
            </div>
          </>
        )}
      </section>

      <Footer />
    </div>
  );
}

// =========================================================================
// FOOTER
// =========================================================================
function Footer() {
  return (
    <footer className="footer">
      <div className="container">
        <div className="cols">
          <div>
            <div className="wordmark" style={{ marginBottom: 16 }}>
              <span className="dot" />
              CloudLayer
            </div>
            <div className="dim" style={{ fontSize: 13, lineHeight: 1.6, maxWidth: 340 }}>
              Real-time Yes/No forecasting benchmark over Polymarket. Six frontier models, one cold prompt, transparent verdicts.
            </div>
            <div className="mono faint" style={{ fontSize: 11, marginTop: 24, letterSpacing: '0.05em' }}>
              v1.0
            </div>
          </div>
          <div>
            <h4>The benchmark</h4>
            <ul>
              <li><a href="/leaderboard" onClick={(e) => { e.preventDefault(); navigate('leaderboard'); }}>Leaderboard</a></li>
              <li><a href="/toppicks" onClick={(e) => { e.preventDefault(); navigate('toppicks'); }}>Top picks</a></li>
              <li><a href="/og" onClick={(e) => { e.preventDefault(); navigate('share'); }}>Share cards</a></li>
            </ul>
          </div>
          <div>
            <h4>Build with us</h4>
            <ul>
              <li><a href="/api/meta">API · /api/meta</a></li>
              <li><a href="/track" onClick={(e) => { e.preventDefault(); navigate('profile'); }}>Track a prompt</a></li>
            </ul>
          </div>
          <div>
            <h4>About</h4>
            <ul>
              <li><a href="#">Mission</a></li>
              <li><a href="#">Methodology</a></li>
              <li><a href="#">Contact</a></li>
            </ul>
          </div>
        </div>
      </div>
    </footer>
  );
}

window.HomePage = HomePage;
window.Footer = Footer;
