// Deterministic mock data so equity curves, trades, events all line up.
const COINS = ['BTC','ETH','BNB','ADA','SOL','XRP','AVAX','DOT'];
const ACCOUNTS = [
  { id: 'binance-main', exchange: 'binance', mode: 'paper',   bridge: 'USDT', current_coin: 'BTC' },
  { id: 'paribu-try',   exchange: 'paribu',  mode: 'testnet', bridge: 'TRY',  current_coin: 'ETH' },
  { id: 'binance-live', exchange: 'binance', mode: 'live',    bridge: 'USDT', current_coin: 'SOL' },
];

// Mulberry32 PRNG so output is stable across reloads.
function rng(seed) {
  let s = seed >>> 0;
  return () => {
    s |= 0; s = s + 0x6D2B79F5 | 0;
    let t = Math.imul(s ^ s >>> 15, 1 | s);
    t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
    return ((t ^ t >>> 14) >>> 0) / 4294967296;
  };
}

const NOW = Date.now();
const HOUR = 3600 * 1000;

// Equity: 24h, 1-min ticks
function buildEquity(seed, base, hours = 168) {
  const r = rng(seed);
  const points = hours * 6; // every 10 min
  const out = [];
  let v = base;
  for (let i = points; i >= 0; i--) {
    const t = NOW - i * 10 * 60 * 1000;
    v = v * (1 + (r() - 0.49) * 0.0035);
    out.push({ t, v: +v.toFixed(2) });
  }
  return out;
}

function buildPairs(seed, currentCoin) {
  const r = rng(seed);
  const out = [];
  for (const a of COINS) {
    for (const b of COINS) {
      if (a === b || a === 'USDT' || b === 'USDT') continue;
      const baseline = +(0.5 + r() * 80).toFixed(4);
      const drift = (r() - 0.5) * 0.12;
      const current = +(baseline * (1 + drift)).toFixed(4);
      const raw = +drift.toFixed(4);
      const eff = +(raw - 0.0025 - r() * 0.003).toFixed(4);
      out.push({
        from: a, to: b, baseline, current, raw_score: raw, eff_score: eff,
        margin: 0.005, multiplier: 1.05, ema_alpha: 0.05,
        last_decision: eff > 0.01 ? 'jump_candidate' : eff < -0.01 ? 'reject_below_threshold' : 'hold',
      });
    }
  }
  return out;
}

function buildTrades(seed, n = 80) {
  const r = rng(seed);
  const states = ['FILLED','FILLED','FILLED','PARTIALLY_FILLED','CANCELED','REJECTED'];
  const out = [];
  let coin = 'BTC';
  for (let i = 0; i < n; i++) {
    const next = COINS.filter(c => c !== coin && c !== 'USDT')[Math.floor(r() * 6)];
    const ts = NOW - (n - i) * (HOUR / 2 + r() * HOUR);
    const qty = +(0.05 + r() * 1.5).toFixed(4);
    const price = +(50 + r() * 70000).toFixed(2);
    const fee = +(qty * price * 0.001).toFixed(4);
    const state = states[Math.floor(r() * states.length)];
    const cid = `pb-${i}-${coin}-${next}-${Math.floor(r()*0xfffff).toString(16).padStart(5,'0')}`;
    const fills = [];
    if (state === 'FILLED' || state === 'PARTIALLY_FILLED') {
      const m = 1 + Math.floor(r() * 3);
      let left = qty;
      for (let k = 0; k < m; k++) {
        const part = k === m - 1 ? left : +(qty / m * (0.7 + r() * 0.6)).toFixed(4);
        left -= part;
        fills.push({ price: +(price * (1 + (r()-0.5)*0.001)).toFixed(2), qty: part, commission: +(part*price*0.001).toFixed(4), isMaker: r() > 0.5 });
      }
    }
    out.push({
      id: i + 1, ts, account: r() > 0.3 ? 'binance-main' : 'paribu-try',
      from: coin, to: next, qty, price, fee, state, client_order_id: cid,
      side: r() > 0.5 ? 'BUY' : 'SELL', symbol: `${next}/USDT`,
      fills,
      outbox_id: 1000 + i,
    });
    if (state === 'FILLED') coin = next;
  }
  return out.reverse();
}

function buildEvents(seed) {
  const r = rng(seed);
  const kinds = ['strategy_decision','tick','dispatch','reconcile','risk_check','outbox_state','depeg_check'];
  const out = [];
  for (let i = 0; i < 600; i++) {
    const ts = NOW - (600 - i) * (60 * 1000) * (0.4 + r() * 0.8);
    const kind = kinds[Math.floor(r() * kinds.length)];
    out.push({
      id: i + 1, kind, at: ts,
      payload: {
        account: r() > 0.5 ? 'binance-main' : 'paribu-try',
        score: +(r()*0.05 - 0.025).toFixed(4),
        coin: COINS[Math.floor(r() * 6)],
      }
    });
  }
  return out;
}

function buildLogs(seed) {
  const r = rng(seed);
  const sevs = ['debug','info','info','info','warn','error'];
  const kinds = ['scout','dispatcher','outbox','reconcile','risk','ws','rest'];
  const msgs = [
    'tick received', 'jump candidate evaluated', 'order acknowledged by exchange',
    'reconcile diff detected', 'depeg guard cleared', 'order failed: insufficient balance',
    'ws reconnect', 'partial fill received', 'kill-switch armed', 'baseline updated',
  ];
  const out = [];
  for (let i = 0; i < 200; i++) {
    const ts = NOW - (200 - i) * 8000 - r() * 2000;
    const sev = sevs[Math.floor(r() * sevs.length)];
    const kind = kinds[Math.floor(r() * kinds.length)];
    const msg = msgs[Math.floor(r() * msgs.length)];
    out.push({
      ts, sev, kind, msg,
      account: r() > 0.5 ? 'binance-main' : 'paribu-try',
      data: {
        coin: COINS[Math.floor(r()*7)],
        score: +(r()*0.1 - 0.05).toFixed(5),
        latency_ms: Math.floor(r() * 220),
        nonce: Math.floor(r() * 9999999),
      }
    });
  }
  return out;
}

const KILL_TRIP_AT = NOW - 9 * HOUR;
const ALERTS = [
  { kind: 'risk_halt', severity: 'error', reason: 'bridge_depeg_low: USDT mid 0.9962 (<0.998)', at: KILL_TRIP_AT, account: 'binance-live' },
  { kind: 'dead_letter', severity: 'warn', reason: 'order failed 3× — moved to dead-letter', at: NOW - 2*HOUR, account: 'binance-main', cid: 'pb-58-ETH-SOL-9a17c' },
  { kind: 'reconcile_diff', severity: 'info', reason: 'local qty 1.2034 vs exchange 1.2030', at: NOW - 30*60*1000, account: 'binance-main' },
  { kind: 'flash_crash', severity: 'warn', reason: 'BTC -4.2% over 60s; pause 5min', at: NOW - 70*60*1000, account: 'binance-main' },
];

const TICKER = COINS.filter(c => c !== 'USDT').map((c, i) => ({
  symbol: `${c}/USDT`,
  last: [62800, 3120, 580, 0.42, 142, 0.51, 31.8, 7.9][i] || 100,
  change: ((i % 3) - 1) * 0.01 * (i + 1) * 0.4,
}));

const CONFIG_YAML = `app:
  name: project-bad-v1
  log_level: info
  http_addr: ":8088"
  metrics_addr: ":9090"
accounts:
  - id: binance-main
    exchange: binance
    mode: paper
    bridge: USDT
    api_key: ***REDACTED***
    api_secret: ***REDACTED***
    coins: [BTC, ETH, BNB, ADA, SOL, XRP, AVAX, DOT]
    notifications:
      webhook: ***REDACTED***
  - id: paribu-try
    exchange: paribu
    mode: testnet
    bridge: TRY
    api_key: ***REDACTED***
    api_secret: ***REDACTED***
    token: ***REDACTED***
    coins: [BTC, ETH, AVAX, DOT]
risk:
  bridge_depeg_lower: 0.998
  bridge_depeg_upper: 1.002
  flash_crash_pct: 0.04
  flash_crash_window_s: 60
  max_consecutive_errors: 3
  kill_switch_persist: true
strategy_config:
  binance-main:
    margin: 0.005
    multiplier: 1.05
    ema_alpha: 0.05
    fee_pct: 0.001
    safety_pct: 0.001
    anti_whipsaw_window_s: 300
  paribu-try:
    margin: 0.0075
    multiplier: 1.05
    ema_alpha: 0.04
    fee_pct: 0.0015
    safety_pct: 0.0012
    anti_whipsaw_window_s: 420`;

const Mock = {
  COINS, ACCOUNTS, TICKER, CONFIG_YAML, ALERTS, KILL_TRIP_AT, NOW, HOUR,
  equity: buildEquity(7, 12500, 168),
  equityShort: buildEquity(13, 12500, 24),
  pairs: buildPairs(101, 'BTC'),
  trades: buildTrades(33, 90),
  events: buildEvents(55),
  logs: buildLogs(77),
};

window.Mock = Mock;
