// ============================================================
// 18% CLUB · DASHBOARD CHARTS (Chart.js, Japandi-styled)
// Ported from the local NQ trading dashboard artifact.
// Exposes: MissionStrip, PriceChart, EquityChart, ReturnChart,
//          TierChart, PlansTable  → window
// ============================================================
const { useEffect: dcUseEffect, useRef: dcUseRef, useState: dcUseState, useMemo: dcUseMemo } = React;

const DC = {
  navy: '#213744', terra: '#AB6A57', sage: '#606C5A', mustard: '#DCB482',
  stone1: '#917F6C', stone2: '#5E5E5E', cream1: '#F3F0E8', cream2: '#E7E1D8',
  border: '#DBD3CD', paper: '#FFFFFF',
  mono: 'ui-monospace, "SF Mono", Menlo, monospace',
  sans: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif'
};
const INITIAL = 500000;

// Shared Chart.js base options
function dcBaseOpts(extra) {
  return Object.assign({
    responsive: true, maintainAspectRatio: false,
    interaction: { mode: 'index', intersect: false },
    plugins: {
      legend: { display: false },
      tooltip: {
        backgroundColor: DC.navy, titleColor: DC.cream1, bodyColor: DC.cream1,
        borderColor: DC.mustard, borderWidth: 1, padding: 10, cornerRadius: 6,
        titleFont: { family: DC.mono, size: 11 }, bodyFont: { family: DC.mono, size: 12 }
      }
    },
    scales: {
      x: { grid: { color: 'rgba(219,211,205,0.4)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, maxRotation: 0, autoSkip: true, maxTicksLimit: 8 } },
      y: { grid: { color: 'rgba(219,211,205,0.55)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 } } }
    }
  }, extra || {});
}
const fmtK = (v) => {const a = Math.abs(v);return (v < 0 ? '−' : '') + (a >= 1000 ? '$' + (a / 1000).toFixed(a >= 10000 ? 0 : 1) + 'K' : '$' + a);};
const shortDate = (iso) => {const [, m, d] = iso.split('-');return `${parseInt(m, 10)}/${parseInt(d, 10)}`;};

// ---------- exit-date lookup from chart marks ----------
function exitMap(chart) {
  const m = {};
  (chart.marks || []).forEach((k) => {if (k.kind === 'win' || k.kind === 'loss') m[k.id] = k.date;});
  return m;
}

// ============================================================
// MISSION STRIP — inception context
// ============================================================
function MissionStrip({ account, kpis, meta }) {
  const days = (() => {
    const a = new Date(account.inception_date),b = new Date(meta.trading_day);
    return Math.max(1, Math.round((b - a) / 864e5));
  })();
  const ret = (account.current_nav_usd - INITIAL) / INITIAL;
  const annualTarget = 0.18;
  const targetEquity = INITIAL * Math.pow(1 + annualTarget, days / 365);
  const pace = account.current_nav_usd - targetEquity;
  const items = [
  { l: 'Account start', v: '$500K', s: account.inception_date },
  { l: 'Days live', v: String(days), s: 'since inception' },
  { l: 'Current equity', v: fmtK(account.current_nav_usd), s: 'realized + open mark', big: true },
  { l: 'Return since start', v: (ret >= 0 ? '+' : '−') + (Math.abs(ret) * 100).toFixed(1) + '%', s: 'vs $500K', cls: ret >= 0 ? 'up' : 'down' },
  { l: 'Pace vs 18% target', v: (pace >= 0 ? '+' : '−') + fmtK(Math.abs(pace)), s: pace >= 0 ? 'ahead of pace' : 'behind pace', cls: pace >= 0 ? 'up' : 'down' }];

  return (
    <div className="dsh-mission">
      {items.map((it, i) =>
      <div key={i} className="dsh-ms-item">
        <div className="dsh-ms-l">{it.l}</div>
        <div className={`dsh-ms-v ${it.big ? 'big' : ''} ${it.cls || ''}`}>{it.v}</div>
        <div className="dsh-ms-s">{it.s}</div>
      </div>
      )}
    </div>);

}

// ============================================================
// generic Chart.js host
// ============================================================
function ChartHost({ build, deps, height }) {
  const ref = dcUseRef(null);
  const inst = dcUseRef(null);
  dcUseEffect(() => {
    if (!ref.current || !window.Chart) return;
    inst.current = build(ref.current);
    return () => {if (inst.current) {try {inst.current.destroy();} catch (e) {}}};
  }, deps || []);
  return <div style={{ position: 'relative', height: height || 300 }}><canvas ref={ref} /></div>;
}

// ============================================================
// NQ PRICE CHART (close line + entry/exit markers) + positions sub-pane
// ============================================================
function PriceChart({ chart, trades }) {
  const ohlc = chart.ohlc || [];
  const labels = ohlc.map((d) => shortDate(d.date));
  const closeByDate = {};ohlc.forEach((d) => closeByDate[d.date] = d.close);
  const idx = {};ohlc.forEach((d, i) => idx[d.date] = i);

  const entries = [],winEx = [],lossEx = [],opens = [];
  (chart.marks || []).forEach((m) => {
    if (idx[m.date] == null) return;
    const pt = { x: idx[m.date], y: m.price };
    if (m.kind === 'entry') entries.push(pt);else
    if (m.kind === 'open') opens.push(pt);else
    if (m.kind === 'win') winEx.push(pt);else
    if (m.kind === 'loss') lossEx.push(pt);
  });
  // Fan out markers that land on the same bar (multiple plans entered/exited the
  // same day at the same price) so each one is individually visible.
  const spread = (pts) => {
    const byX = {};
    pts.forEach((p) => {(byX[p.x] = byX[p.x] || []).push(p);});
    Object.values(byX).forEach((g) => {
      if (g.length < 2) return;
      const step = Math.min(0.16, 0.62 / (g.length - 1));
      g.forEach((p, i) => {p.x = p.x + (i - (g.length - 1) / 2) * step;});
    });
    return pts;
  };
  spread(entries);spread(opens);spread(winEx);spread(lossEx);

  // open positions per trading day
  const xm = exitMap(chart);
  const posData = ohlc.map((d) => {
    let n = 0;
    trades.forEach((t) => {
      const entry = t.date;
      const exit = xm[t.id];
      if (entry <= d.date && (!exit || exit > d.date)) n++;
    });
    return n;
  });

  return (
    <div className="dsh-card">
      <div className="dsh-card-h">NQ daily close <span className="dsh-hint">price · markers · open positions</span></div>
      <div className="dsh-legend">
        <span className="dsh-lg"><i className="dsh-tri up navy" />Entry</span>
        <span className="dsh-lg"><i className="dsh-tri up mustard" />Open entry</span>
        <span className="dsh-lg"><i className="dsh-tri dn sage" />Exit · win</span>
        <span className="dsh-lg"><i className="dsh-tri dn terra" />Exit · loss</span>
      </div>
      <ChartHost height={300} deps={[ohlc.length]} build={(cv) =>
      new window.Chart(cv, {
        type: 'line',
        data: { labels, datasets: [
          { label: 'NQ close', data: ohlc.map((d) => d.close), borderColor: DC.navy, backgroundColor: 'rgba(33,55,68,0.06)', borderWidth: 2, fill: true, tension: 0.25, pointRadius: 0, order: 5 },
          { label: 'Entry', type: 'scatter', data: entries, parsing: false, pointStyle: 'triangle', pointRadius: 7, pointBackgroundColor: DC.navy, pointBorderColor: DC.paper, pointBorderWidth: 1, order: 1 },
          { label: 'Open entry', type: 'scatter', data: opens, parsing: false, pointStyle: 'triangle', pointRadius: 7, pointBackgroundColor: DC.mustard, pointBorderColor: DC.paper, pointBorderWidth: 1, order: 1 },
          { label: 'Exit · win', type: 'scatter', data: winEx, parsing: false, pointStyle: 'triangle', rotation: 180, pointRadius: 7, pointBackgroundColor: DC.sage, pointBorderColor: DC.paper, pointBorderWidth: 1, order: 1 },
          { label: 'Exit · loss', type: 'scatter', data: lossEx, parsing: false, pointStyle: 'triangle', rotation: 180, pointRadius: 7, pointBackgroundColor: DC.terra, pointBorderColor: DC.paper, pointBorderWidth: 1, order: 1 }]
        },
        options: dcBaseOpts({ scales: {
            x: { grid: { color: 'rgba(219,211,205,0.4)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, maxRotation: 0, autoSkip: true, maxTicksLimit: 9 } },
            y: { grid: { color: 'rgba(219,211,205,0.55)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, callback: (v) => (v / 1000).toFixed(0) + 'K' } }
          } })
      })
      } />
      <div className="dsh-pos-h">Open positions</div>
      <ChartHost height={70} deps={[ohlc.length]} build={(cv) =>
      new window.Chart(cv, {
        type: 'bar',
        data: { labels, datasets: [{ data: posData, backgroundColor: 'rgba(96,108,90,0.55)', borderRadius: 2, barPercentage: 1, categoryPercentage: 0.9 }] },
        options: dcBaseOpts({ plugins: { legend: { display: false }, tooltip: { enabled: true, backgroundColor: DC.navy, callbacks: { label: (c) => c.parsed.y + ' open' } } },
          scales: { x: { display: false }, y: { grid: { display: false }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 9 }, stepSize: 1, precision: 0 } } } })
      })
      } />
    </div>);

}

// ============================================================
// ACCOUNT EQUITY CURVE
// ============================================================
function EquityChart({ equity }) {
  const labels = equity.map((p) => shortDate(p.date));
  return (
    <div className="dsh-card">
      <div className="dsh-card-h">Account equity <span className="dsh-hint">live (mark-to-market) vs realized · starts at $500K</span></div>
      <div className="dsh-legend">
        <span className="dsh-lg"><i className="dsh-sw sage" />Live equity</span>
        <span className="dsh-lg"><i className="dsh-sw mustard dash" />Realized equity</span>
      </div>
      <ChartHost height={220} deps={[equity.length]} build={(cv) =>
      new window.Chart(cv, {
        type: 'line',
        data: { labels, datasets: [
          { label: 'Live equity', data: equity.map((p) => p.mark_usd), borderColor: DC.sage, backgroundColor: 'rgba(96,108,90,0.12)', borderWidth: 2.5, fill: true, tension: 0.3, pointRadius: 0 },
          { label: 'Realized equity', data: equity.map((p) => p.realized_usd), borderColor: DC.mustard, borderWidth: 2, borderDash: [6, 5], fill: false, tension: 0.3, pointRadius: 0 }]
        },
        options: dcBaseOpts({ plugins: {
            legend: { display: false },
            tooltip: { backgroundColor: DC.navy, callbacks: { label: (c) => c.dataset.label + ': $' + Math.round(c.parsed.y).toLocaleString() } }
          }, scales: {
            x: { grid: { display: false }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, maxRotation: 0, autoSkip: true, maxTicksLimit: 8 } },
            y: { grid: { color: 'rgba(219,211,205,0.55)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, callback: (v) => '$' + (v / 1000).toFixed(0) + 'K' } }
          } })
      })
      } />
    </div>);

}

// ============================================================
// RETURN % SINCE INCEPTION + 18% ANNUAL-TARGET OVERLAY
// ============================================================
function ReturnChart({ equity, account }) {
  const labels = equity.map((p) => shortDate(p.date));
  const incep = new Date(account.inception_date);
  const actual = equity.map((p) => (p.mark_usd - INITIAL) / INITIAL * 100);
  const target = equity.map((p) => {
    const days = Math.max(0, (new Date(p.date) - incep) / 864e5);
    return (Math.pow(1.18, days / 365) - 1) * 100;
  });
  const lastA = actual[actual.length - 1] || 0;
  const lastT = target[target.length - 1] || 0;
  const above = lastA >= lastT;
  return (
    <div className="dsh-card">
      <div className="dsh-card-h">Return % since inception <span className="dsh-hint">vs $500K start</span>
        <span className={`dsh-target-badge ${above ? 'above' : 'below'}`}>{above ? 'above target' : 'below target'}</span>
      </div>
      <ChartHost height={220} deps={[equity.length]} build={(cv) =>
      new window.Chart(cv, {
        type: 'line',
        data: { labels, datasets: [
          { label: 'Return', data: actual, borderColor: DC.navy, backgroundColor: 'rgba(33,55,68,0.08)', borderWidth: 2.5, fill: true, tension: 0.3, pointRadius: 0 }]
        },
        options: dcBaseOpts({ plugins: {
            legend: { display: false },
            tooltip: { backgroundColor: DC.navy, callbacks: { label: (c) => 'Return: ' + c.parsed.y.toFixed(1) + '%' } }
          }, scales: {
            x: { grid: { display: false }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, maxRotation: 0, autoSkip: true, maxTicksLimit: 8 } },
            y: { grid: { color: 'rgba(219,211,205,0.55)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, callback: (v) => v.toFixed(0) + '%' } }
          } })
      })
      } />
    </div>);

}

// ============================================================
// P&L BY PLAN TIER
// ============================================================
function TierChart({ trades }) {
  const order = ['tier-1', 'tier-2', 'aggressive'];
  const lbl = { 'tier-1': 'Tier 1', 'tier-2': 'Tier 2', 'aggressive': 'Aggressive' };
  const sums = {};order.forEach((k) => sums[k] = 0);
  trades.forEach((t) => {
    const v = t.result === 'open' ? t.unrealized_pnl_usd || 0 : t.realized_pnl_usd || 0;
    if (sums[t.tier] == null) sums[t.tier] = 0;
    sums[t.tier] += v;
  });
  const keys = order.filter((k) => sums[k] !== undefined);
  const vals = keys.map((k) => sums[k]);
  return (
    <div className="dsh-card">
      <div className="dsh-card-h">P&amp;L by plan tier <span className="dsh-hint">realized + open mark</span></div>
      <ChartHost height={220} deps={[trades.length]} build={(cv) =>
      new window.Chart(cv, {
        type: 'bar',
        data: { labels: keys.map((k) => lbl[k] || k), datasets: [{ data: vals, backgroundColor: vals.map((v) => v >= 0 ? 'rgba(96,108,90,0.8)' : 'rgba(171,106,87,0.8)'), borderRadius: 4, barPercentage: 0.6 }] },
        options: dcBaseOpts({ plugins: { legend: { display: false }, tooltip: { backgroundColor: DC.navy, callbacks: { label: (c) => fmtK(c.parsed.y) } } },
          scales: { x: { grid: { display: false }, ticks: { color: DC.navy, font: { family: DC.sans, size: 12, weight: '700' } } },
            y: { grid: { color: 'rgba(219,211,205,0.55)' }, ticks: { color: DC.stone1, font: { family: DC.mono, size: 10 }, callback: (v) => fmtK(v) } } } })
      })
      } />
    </div>);

}

// ============================================================
// FULL PLANS TABLE — sortable + searchable
// ============================================================
function PlansTable({ trades, chart }) {
  const xm = exitMap(chart);
  const rows = dcUseMemo(() => trades.map((t) => {
    const pnl = t.result === 'open' ? t.unrealized_pnl_usd || 0 : t.realized_pnl_usd || 0;
    return {
      id: t.id, date: t.date, exit: xm[t.id] || '', dir: t.direction, tier: t.tier,
      entry: t.entry_price, exitp: t.exit_price, pnl, result: t.result
    };
  }), [trades]);
  const [sort, setSort] = dcUseState({ k: 'date', dir: -1 });
  const [q, setQ] = dcUseState('');
  const tierLbl = (t) => t === 'tier-1' ? 'T1' : t === 'tier-2' ? 'T2' : 'AGG';

  const view = dcUseMemo(() => {
    let r = rows;
    if (q.trim()) {const s = q.toLowerCase();r = r.filter((x) => (x.id + ' ' + x.tier + ' ' + x.dir + ' ' + x.result).toLowerCase().includes(s));}
    const k = sort.k;
    r = r.slice().sort((a, b) => {
      let av = a[k],bv = b[k];
      if (typeof av === 'string') {av = av || '';bv = bv || '';return av < bv ? -sort.dir : av > bv ? sort.dir : 0;}
      return ((av || 0) - (bv || 0)) * sort.dir;
    });
    return r;
  }, [rows, sort, q]);

  const th = (k, label) =>
  <th onClick={() => setSort((s) => ({ k, dir: s.k === k ? -s.dir : 1 }))} className={sort.k === k ? 'on' : ''}>
    {label}<span className="dsh-sort">{sort.k === k ? sort.dir > 0 ? '▲' : '▼' : ''}</span>
  </th>;

  return (
    <div className="dsh-card">
      <div className="dsh-table-head">
        <div className="dsh-card-h" style={{ margin: 0 }}>All plans <span className="dsh-hint">{rows.length} total · sortable · searchable</span></div>
        <input className="dsh-search" placeholder="Search id / tier / result…" value={q} onChange={(e) => setQ(e.target.value)} />
      </div>
      <div className="dsh-table-wrap">
        <table className="dsh-table">
          <thead>
            <tr>
              {th('id', 'Plan')}{th('date', 'Entry')}{th('exit', 'Exit')}{th('dir', 'Dir')}
              {th('tier', 'Tier')}{th('entry', 'Entry px')}{th('exitp', 'Exit px')}{th('result', 'Status')}{th('pnl', 'P&L')}
            </tr>
          </thead>
          <tbody>
            {view.map((r) =>
            <tr key={r.id} className={r.result}>
              <td className="mono"><a href={`index.html#trade=${r.id}`}>{r.id}</a></td>
              <td className="mono">{r.date ? shortDate(r.date) : '—'}</td>
              <td className="mono">{r.exit ? shortDate(r.exit) : '—'}</td>
              <td>{r.dir === 'long' ? 'Long' : 'Short'}</td>
              <td>{tierLbl(r.tier)}</td>
              <td className="mono">{r.entry ? r.entry.toLocaleString() : '—'}</td>
              <td className="mono">{r.exitp ? r.exitp.toLocaleString() : '—'}</td>
              <td><span className={`dsh-badge ${r.result}`}>{r.result}</span></td>
              <td className={`mono dsh-pnl ${r.pnl >= 0 ? 'pos' : 'neg'}`}>{r.pnl >= 0 ? '+' : '−'}${Math.abs(r.pnl).toLocaleString()}</td>
            </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>);

}

// ============================================================
// DATE-RANGE FILTER BAR
// ============================================================
function FilterBar({ range, customStart, onRange, onCustom, lastDate, firstDate }) {
  const opts = [['all', 'All'], ['30d', '30D'], ['14d', '14D'], ['7d', '7D']];
  return (
    <div className="dsh-filter">
      <span className="dsh-filter-l">Window</span>
      <div className="dsh-filter-btns">
        {opts.map(([k, lbl]) =>
        <button key={k} className={`dsh-fbtn ${range === k && !customStart ? 'on' : ''}`} onClick={() => onRange(k)}>{lbl}</button>
        )}
      </div>
      <span className="dsh-filter-from">from</span>
      <input
        type="date"
        className="dsh-fdate"
        value={customStart || ''}
        min={firstDate}
        max={lastDate}
        onChange={(e) => onCustom(e.target.value)} />
      {customStart && <button className="dsh-fclear" onClick={() => onCustom('')} aria-label="Clear start date">×</button>}
    </div>);

}

Object.assign(window, { MissionStrip, PriceChart, EquityChart, ReturnChart, TierChart, PlansTable, FilterBar });