// Cortex — shared design tokens + data source.
// Visual tokens are verbatim from the Take A (Research Terminal) design.
// Data is loaded from window.CORTEX_DATA when present (generated by the
// `cortex-web` CLI). Falls back to the design's built-in mocks when missing,
// so this file runs standalone in a static browser test.

const CX = {
  bg:         '#0B0C0F',
  panel:      '#111317',
  panelHi:    '#15181D',
  panelHover: '#181B22',
  line:       'rgba(255,255,255,0.06)',
  lineHi:     'rgba(255,255,255,0.12)',
  text:       '#E8E9EB',
  textHi:     '#FFFFFF',
  dim:        'rgba(232,233,235,0.56)',
  faint:      'rgba(232,233,235,0.36)',
  veryFaint:  'rgba(232,233,235,0.20)',
  accent:     '#7BE5A4',
  accentDim:  'rgba(123,229,164,0.18)',
  accentVery: 'rgba(123,229,164,0.08)',
  red:        '#F0846A',
  redDim:     'rgba(240,132,106,0.18)',
  amber:      '#E8C870',
  amberDim:   'rgba(232,200,112,0.16)',
  blue:       '#7AB6F0',
  blueDim:    'rgba(122,182,240,0.16)',
  display:    '"GT America","Söhne","Inter",system-ui,sans-serif',
  mono:       '"Berkeley Mono","JetBrains Mono","IBM Plex Mono",ui-monospace,monospace',
};

// ─── helpers ──────────────────────────────────────────────────────────────

function Mono({ children, style, ...r }) {
  return <span style={{ fontFamily: CX.mono, ...style }} {...r}>{children}</span>;
}

function Score({ v, w = 56 }) {
  const lit = Math.max(0, Math.min(100, v));
  const color = v >= 70 ? CX.accent : v >= 40 ? CX.amber : CX.red;
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', gap: 8, width: w + 28 }}>
      <div style={{ width: w, height: 4, background: CX.line, position: 'relative' }}>
        <div style={{ position: 'absolute', inset: 0, width: `${lit}%`, background: color, opacity: 0.85 }} />
      </div>
      <Mono style={{ fontSize: 11, color: CX.text, width: 22, textAlign: 'right' }}>{Math.round(v)}</Mono>
    </div>
  );
}

// Responsive layout flag. Components branch on this to render the
// mobile-adapted shell (horizontal tab nav, slimmed topbar). Desktop
// layout is unchanged when isMobile === false.
function useIsMobile(threshold = 720) {
  const get = () => typeof window !== 'undefined' && window.innerWidth <= threshold;
  const [m, setM] = React.useState(get);
  React.useEffect(() => {
    const onResize = () => setM(get());
    window.addEventListener('resize', onResize);
    return () => window.removeEventListener('resize', onResize);
  }, [threshold]);
  return m;
}

function Chip({ on, onClick, children }) {
  return (
    <button
      onClick={onClick}
      style={{
        appearance: 'none', border: 'none', cursor: 'pointer',
        padding: '6px 10px',
        background: on ? CX.accentDim : 'transparent',
        color: on ? CX.accent : CX.dim,
        border: `1px solid ${on ? CX.accent : CX.line}`,
        fontFamily: CX.mono, fontSize: 11, letterSpacing: '0.06em',
        textTransform: 'lowercase',
        transition: 'color .12s, background .12s, border-color .12s',
      }}
    >
      {children}
    </button>
  );
}

// ─── data source ──────────────────────────────────────────────────────────
// Live data → window.CORTEX_DATA (generated by `cortex-web build`).
// If absent or empty, fall back to the original design fixtures.

const _LIVE = (typeof window !== 'undefined' && window.CORTEX_DATA) || null;

const BUCKETS    = _LIVE?.BUCKETS    || ['cheap_decent', 'compounder', 'danger', 'inflection', 'pullback'];
const COUNTRIES  = _LIVE?.COUNTRIES  || ['Sverige', 'Norge', 'Danmark', 'Finland', 'Island'];
const SECTORS    = _LIVE?.SECTORS    || [
  'Informationsteknik', 'Industri', 'Hälsovård', 'Dagligvaror',
  'Sällanköpsvaror', 'Material', 'Energi', 'Kraftförsörjning',
  'Finans & Fastighet', 'Kommunikation',
];

// Deterministic pseudo-random used by the mock-data path and by the
// design's price/equity/sparkline placeholder helpers in other pages.
function rng(seed) {
  let s = seed | 0;
  return () => { s = (s * 1664525 + 1013904223) | 0; return ((s >>> 0) % 10000) / 10000; };
}

function _mockRows() {
  // Verbatim from the original design — kept so this file degrades to a
  // working standalone demo when no data.js is present.
  const tickers = [
    ['GENI',    'Generic Sweden',           'Sverige', 'Informationsteknik', 'compounder'],
    ['RVRC',    'Revolutionrace',           'Sverige', 'Sällanköpsvaror',    'compounder'],
    ['PEXIP',   'Pexip Holding',            'Norge',   'Informationsteknik', 'compounder'],
    ['MSAB B',  'Micro Systemation',        'Sverige', 'Informationsteknik', 'compounder'],
    ['MEDI',    'Medistim',                 'Norge',   'Hälsovård',          'compounder'],
    ['SYNSAM',  'Synsam Group',             'Sverige', 'Sällanköpsvaror',    'compounder'],
    ['BIOG B',  'BioGaia',                  'Sverige', 'Dagligvaror',        'compounder'],
    ['ACAD',    'AcadeMedia',               'Sverige', 'Industri',           'compounder'],
    ['OPTER',   'Opter',                    'Sverige', 'Informationsteknik', 'compounder'],
    ['HEXP B',  'Hexpol',                   'Sverige', 'Material',           'cheap_decent'],
    ['SAGA B',  'Saga Forest Products',     'Sverige', 'Material',           'inflection'],
    ['EOLU B',  'Eolus Vind',               'Sverige', 'Kraftförsörjning',   'inflection'],
    ['KAMUX',   'Kamux',                    'Finland', 'Sällanköpsvaror',    'inflection'],
    ['ORSTED',  'Ørsted',                   'Danmark', 'Kraftförsörjning',   'danger'],
    ['MAERSK',  'A.P. Møller-Mærsk',        'Danmark', 'Industri',           'danger'],
  ];
  const r = rng(20260514);
  return tickers.map(([ticker, name, country, sector, bucket], i) => {
    const base = bucket === 'compounder' ? 70 : bucket === 'cheap_decent' ? 60 : bucket === 'inflection' ? 65 : bucket === 'pullback' ? 50 : 35;
    const jit = (lo, hi) => Math.round(lo + r() * (hi - lo));
    const q = jit(base - 10, Math.min(98, base + 22));
    const v = jit(bucket === 'cheap_decent' ? 70 : bucket === 'danger' ? 20 : 35, bucket === 'cheap_decent' ? 96 : bucket === 'danger' ? 45 : 80);
    const g = jit(bucket === 'compounder' ? 60 : 30, bucket === 'compounder' ? 95 : 80);
    const m = jit(bucket === 'inflection' ? 60 : bucket === 'pullback' ? 10 : 30, bucket === 'inflection' ? 95 : bucket === 'pullback' ? 40 : 85);
    const inf = jit(bucket === 'inflection' ? 70 : 25, bucket === 'inflection' ? 96 : 70);
    const risk = jit(bucket === 'danger' ? 75 : 18, bucket === 'danger' ? 95 : 60);
    return {
      bucket, rank: 0, ticker, name, country, sector,
      quality: q, value: v, growth: g, momentum: m, inflection: inf, risk,
      mcap_bucket: i % 5 === 0 ? 'micro' : i % 3 === 0 ? 'small' : 'small_mid',
      liquidity: risk > 70 ? 'thin' : (i % 6 === 0 ? 'ok' : 'liquid'),
      mcap_eur: jit(60, 1800),
      ev_ebit: (jit(40, 240) / 10).toFixed(1),
      fcf_yield: ((r() - 0.3) * 14).toFixed(1),
      thirty_d: ((r() - 0.45) * 18).toFixed(1),
      held: bucket === 'compounder' && r() > 0.55,
      watch: bucket === 'inflection' || (bucket === 'pullback' && r() > 0.5),
      flag: bucket === 'danger' ? 'AVOID' : (bucket === 'compounder' && r() > 0.7 ? 'BUY' : (bucket === 'inflection' && i < 18 ? 'NEW' : '')),
    };
  });
}

const ROWS = (_LIVE?.ROWS && _LIVE.ROWS.length > 0) ? _LIVE.ROWS : _mockRows();

// Preserve persisted queue ranks when live data is present. Mock fallback rows
// have no persisted rank, so rank those client-side only in demo mode.
(function rank() {
  if (_LIVE?.ROWS && _LIVE.ROWS.length > 0) return;
  const composite = (r) => r.quality * 0.35 + r.growth * 0.25 + r.inflection * 0.2 + r.value * 0.15 - r.risk * 0.25;
  const byBucket = {};
  ROWS.forEach((r) => { (byBucket[r.bucket] ??= []).push(r); });
  Object.values(byBucket).forEach((list) => {
    list.sort((a, b) => composite(b) - composite(a));
    list.forEach((r, i) => { r.rank = i + 1; });
  });
})();

// Optional extra payloads piped through to pages that want them.
const SIMILAR_BY_TICKER = _LIVE?.SIMILAR_BY_TICKER || {};
const BACKTEST          = _LIVE?.BACKTEST          || null;
const PREDICTIONS       = _LIVE?.PREDICTIONS       || { rows: [], summary: [], selected_model: null, asof: null, count: 0 };
const WATCHLIST         = _LIVE?.WATCHLIST         || null;
const NOTES_BY_TICKER   = _LIVE?.NOTES_BY_TICKER   || {};
const PRICE_HISTORY     = _LIVE?.PRICE_HISTORY     || { dates: [], closes: {} };
const META              = _LIVE?.META              || {};

Object.assign(window, {
  CX, Mono, Score, Chip, useIsMobile,
  BUCKETS, COUNTRIES, SECTORS, ROWS,
  SIMILAR_BY_TICKER, BACKTEST, PREDICTIONS, WATCHLIST, NOTES_BY_TICKER, PRICE_HISTORY, META,
  rng,
});
