;(function () {
/* DiscoverPage — Leveraged Trade discovery surface. Search, category pills,
   watchlist, top movers, quick category tiles, news headlines. Renders the
   scrollable body only; the shell handles top bar and bottom nav. */

const CATEGORIES = [
  { key: 'all',         label: 'All' },
  { key: 'forex',       label: 'Forex' },
  { key: 'indices',     label: 'Indices' },
  { key: 'commodities', label: 'Commodities' },
  { key: 'crypto',      label: 'Crypto' },
  { key: 'stocks',      label: 'Stocks' },
];

/* Economic Calendar — upcoming high-impact macro releases shown on
   the discover page. Exposed on window for the voice agent's
   get_economic_calendar tool. impact 1-3, higher = more important. */
window.ECONOMIC_CALENDAR = [
  { time: 'Mon 13:30', currency: 'USD', impact: 3, event: 'CPI YoY (Apr)',          forecast: '2.4%',  previous: '2.6%' },
  { time: 'Wed 18:00', currency: 'USD', impact: 3, event: 'FOMC Rate Decision',     forecast: '4.50%', previous: '4.50%' },
  { time: 'Thu 12:30', currency: 'EUR', impact: 2, event: 'ECB Press Conference',   forecast: '—',     previous: '—' },
  { time: 'Fri 13:30', currency: 'USD', impact: 3, event: 'Non-Farm Payrolls',      forecast: '190K',  previous: '228K' },
];

/* Local SectionHeader override — brief calls for 16px Gilroy SemiBold ink
   left + 13px Inter Medium teal "See all" right (no chevron). */
const Header = ({ title, action, onActionPress }) => (
  <div style={styles.headerRow}>
    <span style={styles.headerTitle}>{title}</span>
    {action ? (
      <button onClick={onActionPress || (() => {})} style={{ ...styles.btnReset, ...styles.headerAction }}>
        {action}
      </button>
    ) : null}
  </div>
);

/* Search input card — non-functional, just visual. */
const SearchBar = () => (
  <div style={styles.searchCard}>
    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" style={{ flexShrink: 0 }}>
      <circle cx="11" cy="11" r="7" stroke={colors.muted} strokeWidth="2" />
      <path d="M20 20l-3.5-3.5" stroke={colors.muted} strokeWidth="2" strokeLinecap="round" />
    </svg>
    <input
      readOnly
      placeholder="Search 5,000+ instruments"
      style={styles.searchInput}
    />
    <span style={styles.kbd}>{'⌘K'}</span>
  </div>
);

/* Horizontal scrolling row of category pills. */
const CategoryPills = ({ active, onSelect }) => (
  <div style={styles.pillsScroller}>
    {CATEGORIES.map((c) => {
      const isActive = c.key === active;
      return (
        <button
          key={c.key}
          onClick={() => onSelect(c.key)}
          style={{
            ...styles.btnReset,
            ...styles.pill,
            backgroundColor: isActive ? 'rgba(0,175,171,0.10)' : colors.white,
            borderColor:    isActive ? colors.teal2 : colors.line,
            color:          isActive ? colors.teal2 : colors.muted2,
          }}
        >
          {c.label}
        </button>
      );
    })}
  </div>
);

/* Watchlist row — symbol circle + name stack + bid/% stack. */
const WatchRow = ({ sym, isLast }) => {
  const up = sym.change >= 0;
  return (
    <button onClick={() => window.goToTrade && window.goToTrade(sym.sym)} style={{ ...styles.btnReset, ...styles.row, borderBottom: isLast ? 'none' : `1px solid ${colors.line}` }}>
      <window.SymbolMark sym={sym} size={40} />
      <div style={styles.nameStack}>
        <span style={styles.symCode}>{sym.sym}</span>
        <span style={styles.symName}>{sym.name}</span>
      </div>
      <div style={styles.priceStack}>
        <span style={styles.bid}>{formatPrice(sym.bid, sym)}</span>
        <span style={{ ...styles.pct, color: up ? colors.green : colors.red }}>
          {(up ? '+' : '-') + Math.abs(sym.change).toFixed(2) + '%'}
        </span>
      </div>
    </button>
  );
};

/* Top mover row — adds a left rank number and replaces price with a sparkline. */
const MoverRow = ({ sym, rank, isLast }) => {
  const up = sym.change >= 0;
  return (
    <button onClick={() => window.goToTrade && window.goToTrade(sym.sym)} style={{ ...styles.btnReset, ...styles.row, borderBottom: isLast ? 'none' : `1px solid ${colors.line}` }}>
      <span style={styles.rank}>{rank}</span>
      <window.SymbolMark sym={sym} size={40} />
      <div style={styles.nameStack}>
        <span style={styles.symCode}>{sym.sym}</span>
        <span style={styles.symName}>{sym.name}</span>
      </div>
      <div style={styles.moverRight}>
        <Sparkline
          up={up}
          data={sym.spark}
          color={up ? colors.green : colors.red}
          width={56}
          height={24}
        />
        <span style={{ ...styles.pct, color: up ? colors.green : colors.red }}>
          {(up ? '+' : '-') + Math.abs(sym.change).toFixed(2) + '%'}
        </span>
      </div>
    </button>
  );
};

/* Inline 24×24 stroked icons for the quick-category tiles. */
const CatIcon = ({ kind }) => {
  const stroke = colors.teal2;
  const common = { width: 24, height: 24, viewBox: '0 0 24 24', fill: 'none' };
  if (kind === 'forex') return (
    <svg {...common}><path d="M4 8h12l-3-3M20 16H8l3 3" stroke={stroke} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
  );
  if (kind === 'indices') return (
    <svg {...common}><path d="M5 19V11M12 19V5M19 19v-7" stroke={stroke} strokeWidth="2" strokeLinecap="round"/></svg>
  );
  if (kind === 'commodities') return (
    <svg {...common}>
      <rect x="4" y="14" width="16" height="6" rx="1.5" stroke={stroke} strokeWidth="2"/>
      <rect x="6" y="8" width="12" height="6" rx="1.5" stroke={stroke} strokeWidth="2"/>
      <rect x="8" y="2" width="8"  height="6" rx="1.5" stroke={stroke} strokeWidth="2"/>
    </svg>
  );
  if (kind === 'crypto') return (
    <svg {...common}><path d="M13 2L4 14h7l-1 8 9-12h-7l1-8z" stroke={stroke} strokeWidth="2" strokeLinejoin="round"/></svg>
  );
  if (kind === 'stocks') return (
    <svg {...common}><path d="M4 18l5-6 4 3 7-9M14 6h6v6" stroke={stroke} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
  );
  if (kind === 'funds') return (
    <svg {...common}><path d="M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7z" stroke={stroke} strokeWidth="2" strokeLinejoin="round"/></svg>
  );
  return null;
};

/* Quick category tile — icon + name + count. */
const CatTile = ({ kind, name, count }) => (
  <button onClick={() => {}} style={{ ...styles.btnReset, ...styles.tile }}>
    <CatIcon kind={kind} />
    <span style={styles.tileName}>{name}</span>
    <span style={styles.tileCount}>{count}</span>
  </button>
);

/* Single news headline row. */
const NewsRow = ({ thumbColor, headline, source, time, isLast }) => (
  <button onClick={() => {}} style={{ ...styles.btnReset, ...styles.newsRow, borderBottom: isLast ? 'none' : `1px solid ${colors.line}` }}>
    <div style={{ ...styles.newsThumb, backgroundColor: thumbColor }} />
    <div style={styles.newsTextStack}>
      <span style={styles.newsHeadline}>{headline}</span>
      <span style={styles.newsMeta}>{source + ' · ' + time}</span>
    </div>
  </button>
);

/* Economic-calendar row — left time block, currency tag + impact dot,
   event name, and a forecast/previous pair on the right. Reads like a
   trader-style econ-calendar entry rather than a news headline. */
const CalendarRow = ({ time, currency, impact, event, forecast, previous, isLast }) => {
  /* Impact dot color: red for high, amber for medium, slate for low.
     Three filled circles; un-filled ones stay grey-200. */
  const impactColors = ['#F04438', '#F79009', '#475467'];
  const dotColor = impactColors[impact - 1] || colors.muted2;
  return (
    <button onClick={() => {}} style={{ ...styles.btnReset, ...styles.calRow, borderBottom: isLast ? 'none' : `1px solid ${colors.line}` }}>
      <div style={styles.calTime}>
        <span style={styles.calTimeText}>{time}</span>
      </div>
      <div style={styles.calBody}>
        <div style={styles.calMetaRow}>
          <span style={styles.calCurrency}>{currency}</span>
          <div style={styles.calImpactRow}>
            {[1, 2, 3].map((i) => (
              <span key={i} style={{
                width: '6px', height: '6px', borderRadius: '3px',
                backgroundColor: i <= impact ? dotColor : '#E4E7EC',
                display: 'inline-block',
              }}/>
            ))}
          </div>
        </div>
        <span style={styles.calEvent}>{event}</span>
      </div>
      <div style={styles.calRight}>
        <span style={styles.calForecastLabel}>Forecast</span>
        <span style={styles.calForecastValue}>{forecast}</span>
        <span style={styles.calPrevLabel}>{'Prev: ' + previous}</span>
      </div>
    </button>
  );
};

const DiscoverPage = () => {
  const [active, setActive] = React.useState('all');

  /* Live symbols from the reactive TradeStore — re-renders on every tick. */
  const allSymbols = window.useAllSymbols();

  /* Markets list filtered by the active pill. */
  const filteredSymbols = active === 'all'
    ? allSymbols
    : allSymbols.filter((s) => s.cat === active);

  const watchlist = (window.WATCHLIST_IDS || [])
    .map((id) => allSymbols.find((s) => s.sym === id))
    .filter(Boolean);
  /* Top movers = the watchlist in its declared order. Sorting by live
     change makes rows reshuffle every tick which reads as flicker on
     the demo; freezing the order keeps the eye anchored. */
  const topMovers = watchlist.slice(0, 5);

  /* Counts for the quick-category tiles. */
  const counts = {
    forex:       allSymbols.filter((s) => s.cat === 'forex').length,
    indices:     allSymbols.filter((s) => s.cat === 'indices').length,
    commodities: allSymbols.filter((s) => s.cat === 'commodities').length,
    crypto:      allSymbols.filter((s) => s.cat === 'crypto').length,
    stocks:      allSymbols.filter((s) => s.cat === 'stocks').length,
  };

  return (
    <div style={styles.outer}>
      <div style={styles.inner}>
        {/* 1. Search */}
        <SearchBar />

        {/* 2. Category pills */}
        <CategoryPills active={active} onSelect={setActive} />

        {/* 3. Watchlist */}
        <div>
          <Header title="Your watchlist" action="See all" />
          <Card padding={{ horizontal: 14, vertical: 12 }}>
            {watchlist.map((s, i) => (
              <WatchRow key={s.sym} sym={s} isLast={i === watchlist.length - 1} />
            ))}
          </Card>
        </div>

        {/* 4. Top movers */}
        <div>
          <Header title="Top movers today" />
          <Card padding={{ horizontal: 14, vertical: 12 }}>
            {topMovers.map((s, i) => (
              <MoverRow key={s.sym} sym={s} rank={i + 1} isLast={i === topMovers.length - 1} />
            ))}
          </Card>
        </div>

        {/* 5. Quick categories grid (2x3). filteredSymbols is computed for
             potential future use by the section above; tiles always show
             totals from TRADE_SYMBOLS counts. */}
        <div>
          <Header title="Browse categories" />
          <div style={styles.grid}>
            <CatTile kind="forex"       name="Forex"       count={counts.forex + ' instruments'} />
            <CatTile kind="indices"     name="Indices"     count={counts.indices + ' instruments'} />
            <CatTile kind="commodities" name="Commodities" count={counts.commodities + ' instruments'} />
            <CatTile kind="crypto"      name="Crypto"      count={counts.crypto + ' instruments'} />
            <CatTile kind="stocks"      name="Stocks"      count={counts.stocks + ' instruments'} />
            <CatTile kind="funds"       name="Funds"       count="12 funds" />
          </div>
        </div>

        {/* 6. Economic Calendar — upcoming high-impact macro releases.
           Data is held in window.ECONOMIC_CALENDAR so the voice agent
           can read it via get_economic_calendar. */}
        <div>
          <Header title="Economic Calendar" action="See all" />
          <Card padding={{ horizontal: 14, vertical: 12 }}>
            {(window.ECONOMIC_CALENDAR || []).map(function (ev, i, arr) {
              return (
                <CalendarRow
                  key={i}
                  time={ev.time}
                  currency={ev.currency}
                  impact={ev.impact}
                  event={ev.event}
                  forecast={ev.forecast}
                  previous={ev.previous}
                  isLast={i === arr.length - 1}
                />
              );
            })}
          </Card>
        </div>

        {/* 7. Footer disclaimer */}
        <div style={styles.footer}>
          Trading involves risk of loss. Past performance does not guarantee future results.
        </div>

        {/* Hidden marker so React keeps filteredSymbols memo alive — the
            categories pill state already drives a re-render of the page. */}
        <div style={{ display: 'none' }}>{filteredSymbols.length}</div>
      </div>
    </div>
  );
};

const styles = {
  /* Page-body wrapper from the brief. */
  outer: {
    flex: 1,
    width: '100%',
    height: '100%',
    overflowY: 'auto',
    WebkitOverflowScrolling: 'touch',
    scrollbarWidth: 'none',
    backgroundColor: colors.bg,
  },
  inner: {
    paddingTop: '16px',
    paddingLeft: '20px',
    paddingRight: '20px',
    paddingBottom: '180px',
    display: 'flex',
    flexDirection: 'column',
    gap: '14px',
  },

  /* Generic button reset. */
  btnReset: {
    border: 'none',
    background: 'transparent',
    padding: 0,
    margin: 0,
    cursor: 'pointer',
    font: 'inherit',
    color: 'inherit',
    textAlign: 'inherit',
  },

  /* Section header. */
  headerRow: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    paddingTop: '4px',
    paddingBottom: '8px',
    paddingLeft: '4px',
    paddingRight: '4px',
  },
  headerTitle: {
    flex: 1,
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '16px',
    color: colors.ink,
  },
  headerAction: {
    fontFamily: 'Inter',
    fontWeight: 500,
    fontSize: '13px',
    color: colors.teal,
    textDecoration: 'none',
  },

  /* Search bar. */
  searchCard: {
    backgroundColor: colors.white,
    borderRadius: '24px',
    height: '48px',
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    paddingLeft: '14px',
    paddingRight: '8px',
    gap: '10px',
    boxShadow: '0px 1px 2px rgba(14, 20, 32, 0.06)',
  },
  searchInput: {
    flex: 1,
    border: 'none',
    outline: 'none',
    background: 'transparent',
    fontFamily: 'Inter',
    fontSize: '14px',
    color: colors.ink,
    height: '24px',
    /* Placeholder color is set globally; we approximate via color when empty. */
  },
  kbd: {
    fontFamily: 'Inter',
    fontWeight: 500,
    fontSize: '11px',
    color: colors.muted2,
    backgroundColor: colors.bg,
    border: `1px solid ${colors.line}`,
    borderRadius: '6px',
    padding: '3px 6px',
    flexShrink: 0,
  },

  /* Category pills. */
  pillsScroller: {
    display: 'flex',
    flexDirection: 'row',
    gap: '8px',
    overflowX: 'auto',
    scrollbarWidth: 'none',
    /* Negative side margin lets pills bleed to the page edges visually
       without breaking the 20px page padding for everything else. */
    marginLeft: '-4px',
    marginRight: '-4px',
    paddingLeft: '4px',
    paddingRight: '4px',
    paddingTop: '2px',
    paddingBottom: '2px',
  },
  pill: {
    height: '36px',
    paddingLeft: '14px',
    paddingRight: '14px',
    borderRadius: '9999px',
    borderWidth: '1px',
    borderStyle: 'solid',
    fontFamily: 'Inter',
    fontWeight: 600,
    fontSize: '13px',
    flexShrink: 0,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    whiteSpace: 'nowrap',
  },

  /* Watchlist / Movers row. */
  row: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    gap: '10px',
    width: '100%',
    paddingTop: '10px',
    paddingBottom: '10px',
  },
  rank: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '11px',
    color: colors.muted2,
    width: '12px',
    marginRight: '6px',
    textAlign: 'center',
    flexShrink: 0,
  },
  nameStack: {
    flex: 1,
    display: 'flex',
    flexDirection: 'column',
    minWidth: 0,
  },
  symCode: {
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '14px',
    color: colors.ink,
  },
  symName: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '12px',
    color: colors.muted,
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
  },
  priceStack: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'flex-end',
    flexShrink: 0,
  },
  bid: {
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '14px',
    color: colors.ink,
    fontFeatureSettings: '"tnum"',
    fontVariantNumeric: 'tabular-nums',
  },
  pct: {
    fontFamily: 'Inter',
    fontWeight: 500,
    fontSize: '12px',
    fontFeatureSettings: '"tnum"',
    fontVariantNumeric: 'tabular-nums',
  },
  moverRight: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'flex-end',
    gap: '2px',
    flexShrink: 0,
  },

  /* Quick categories grid. */
  grid: {
    display: 'grid',
    gridTemplateColumns: '1fr 1fr',
    gap: '10px',
  },
  tile: {
    backgroundColor: colors.white,
    borderRadius: '16px',
    padding: '14px',
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'flex-start',
    gap: '8px',
    boxShadow: '0px 1px 2px rgba(14, 20, 32, 0.06)',
  },
  tileName: {
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '14px',
    color: colors.ink,
  },
  tileCount: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '12px',
    color: colors.muted,
  },

  /* Economic-calendar row. */
  calRow: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    gap: '10px',
    width: '100%',
    paddingTop: '12px',
    paddingBottom: '12px',
  },
  calTime: {
    width: '64px',
    flexShrink: 0,
    display: 'flex',
    alignItems: 'center',
  },
  calTimeText: {
    fontFamily: 'Inter',
    fontWeight: 500,
    fontSize: '12px',
    color: colors.muted,
    fontVariantNumeric: 'tabular-nums',
  },
  calBody: {
    flex: 1,
    display: 'flex',
    flexDirection: 'column',
    gap: '3px',
    minWidth: 0,
  },
  calMetaRow: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'center',
    gap: '8px',
  },
  calCurrency: {
    fontFamily: 'Gilroy',
    fontWeight: 700,
    fontSize: '10px',
    color: colors.muted2,
    letterSpacing: '0.3px',
  },
  calImpactRow: {
    display: 'flex',
    flexDirection: 'row',
    gap: '2px',
    alignItems: 'center',
  },
  calEvent: {
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '13px',
    color: colors.ink,
    overflow: 'hidden',
    textOverflow: 'ellipsis',
    whiteSpace: 'nowrap',
  },
  calRight: {
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'flex-end',
    flexShrink: 0,
    gap: '1px',
  },
  calForecastLabel: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '10px',
    color: colors.muted2,
  },
  calForecastValue: {
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '13px',
    color: colors.ink2,
    fontVariantNumeric: 'tabular-nums',
  },
  calPrevLabel: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '10px',
    color: colors.muted2,
    fontVariantNumeric: 'tabular-nums',
  },

  /* News row. */
  newsRow: {
    display: 'flex',
    flexDirection: 'row',
    alignItems: 'flex-start',
    gap: '10px',
    width: '100%',
    paddingTop: '10px',
    paddingBottom: '10px',
  },
  newsThumb: {
    width: '24px',
    height: '24px',
    borderRadius: '6px',
    flexShrink: 0,
    marginTop: '2px',
  },
  newsTextStack: {
    flex: 1,
    display: 'flex',
    flexDirection: 'column',
    gap: '2px',
    minWidth: 0,
  },
  newsHeadline: {
    fontFamily: 'Gilroy',
    fontWeight: 600,
    fontSize: '13px',
    color: colors.ink,
    lineHeight: '17px',
    display: '-webkit-box',
    WebkitLineClamp: 2,
    WebkitBoxOrient: 'vertical',
    overflow: 'hidden',
  },
  newsMeta: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '12px',
    color: colors.muted,
  },

  /* Footer disclaimer. */
  footer: {
    fontFamily: 'Inter',
    fontWeight: 400,
    fontSize: '11px',
    color: colors.muted2,
    textAlign: 'center',
    paddingTop: '16px',
    paddingBottom: '16px',
  },
};

Object.assign(window, { DiscoverPage });
})();
