// Dashboard — page composition. Mirrors Figma node 7367:16497.
const { useState, useRef, useEffect } = React;

/* ---------------- small shared pieces ---------------- */

function Card({ className = '', children }) {
  return <section className={`db-card ${className}`}>{children}</section>;
}

function CardHead({ title, children }) {
  return (
    <header className="db-card__head">
      <h2 className="db-eyebrow">{title}</h2>
      {children ? <div className="db-card__head-r">{children}</div> : null}
    </header>
  );
}

function Badge({ tone = 'brand', children }) {
  return <span className={`db-badge db-badge--${tone}`}>{children}</span>;
}

// The pill is the only place the card says where an account's numbers came
// from, so hovering it opens the provider detail (Hint lives in db-modals.jsx).
function StatusPill({ status, link }) {
  const s = DB.STATUS[status];
  if (!s) return null;

  const pill = (
    <span className={`db-status db-status--${s.tone}`}>
      {s.dot && <span className="db-status__dot" />}
      {s.icon && <Icon name={s.icon} style={{ width: 12, height: 12 }} />}
      {s.label}
    </span>
  );

  if (!s.hint) return pill;

  const rows = s.meta && link
    ? [`Last update: ${link.lastUpdate}`,
       `Linking Provider: ${link.provider}`,
       `Financial Institution: ${link.institution}`]
    : null;

  return <WithHint title={s.hint} rows={rows}>{pill}</WithHint>;
}

function Metric({ label, value, change, divided }) {
  return (
    <div className={`db-metric ${divided ? 'is-divided' : ''}`}>
      <span className="db-metric__k">{label}</span>
      <span className="db-metric__v tabular">{typeof value === 'number' ? DB.money(value) : value}</span>
      {change && <span className="db-status db-status--success">{change}</span>}
    </div>
  );
}

// Ghost select used in card headers. Opens a real menu so the prototype is
// clickable rather than decorative.
function Select({ label, value, options, onChange, width }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const away = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', away);
    return () => document.removeEventListener('mousedown', away);
  }, [open]);

  return (
    <div className="db-select" ref={ref} style={width ? { minWidth: width } : undefined}>
      <button type="button" className={`db-select__btn ${open ? 'is-open' : ''}`} onClick={() => setOpen(!open)}>
        {label && <span className="db-select__k">{label}</span>}
        <span className="db-select__v">{value}</span>
        <Icon name="chevron-down" style={{ width: 16, height: 16, opacity: .7 }} />
      </button>
      {open && (
        <div className="db-select__menu" role="listbox">
          {options.map((o) => (
            <button key={o} type="button" role="option" aria-selected={o === value}
              className={`db-select__opt ${o === value ? 'is-on' : ''}`}
              onClick={() => { onChange(o); setOpen(false); }}>
              {o}
              {o === value && <Icon name="check" style={{ width: 14, height: 14 }} />}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function LinkOut({ children, href = '#' }) {
  return (
    <a className="db-link" href={href}>
      <span className="db-link__t">{children}</span>
      <Icon name="arrow-up-right" style={{ width: 18, height: 18 }} />
    </a>
  );
}

/* ---------------- 1. Plan projections ---------------- */

function PlanProjections() {
  const p = DB.planConfidence;
  return (
    <Card>
      <CardHead title="Plan projections" />
      <div className="db-pp">
        <div className="db-pp__col">
          {/* Monte Carlo only drives Plan Confidence, so the link lives here rather than in the card head. */}
          <div className="db-pp__hd">
            <span className="db-pp__k">Plan Confidence</span>
            <LinkOut href="Plan%20Confidence.html">Monte Carlo Analysis</LinkOut>
          </div>
          <Badge tone="brand">{p.simulations}</Badge>
          <div className="db-pp__gauge">
            <ConfidenceGauge pct={p.pct} />
            <span className="db-pp__pct tabular">{p.pct}%</span>
            <span className="db-status db-status--success">{p.verdict}</span>
          </div>
        </div>

        <div className="db-pp__rule" />

        <div className="db-pp__col db-pp__col--pad">
          <span className="db-pp__k">End of Plan Outlook ({p.endOfPlanYear})</span>
          <Badge tone="neutral">{p.basis}</Badge>
          <div className="db-metrics">
            <Metric label="End of Plan – Investments" value={p.endOfPlanInvestments} />
            <Metric label="End of Plan – Net Worth" value={p.endOfPlanNetWorth} divided />
          </div>
        </div>
      </div>
    </Card>
  );
}

/* ---------------- 2. Asset allocation ---------------- */

function AllocationCard() {
  const a = DB.allocation;
  const [chartType, setChartType] = useState('Pie');
  const [active, setActive] = useState(-1);
  const total = a.slices.reduce((s, x) => s + x.pct, 0);

  return (
    <Card className="db-alloc">
      <CardHead title="Asset Allocation">
        <Select label="Chart type:" value={chartType} options={['Pie', 'Bar']} onChange={setChartType} />
      </CardHead>
      <div className={`db-alloc__body ${chartType === 'Bar' ? 'is-bar' : ''}`}>
        {chartType === 'Pie' ? (
          <div className="db-alloc__chart">
            <AllocationDonut slices={a.slices} active={active} onHover={setActive} />
            <div className="db-alloc__center">
              <span className="db-alloc__total tabular">{DB.money(a.total)}</span>
              <span className="db-alloc__cap">{a.caption}</span>
            </div>
          </div>
        ) : (
          <>
            {/* the bar variant carries the total above the bar, as designed */}
            <div className="db-alloc__hero">
              <span className="db-alloc__total tabular">{DB.money(a.total)}</span>
              <span className="db-alloc__cap">{a.caption}</span>
            </div>
            <div className="db-alloc__bar">
              {a.slices.map((s, i) => (
                <span key={i} className="db-alloc__bar-seg"
                  style={{ flex: s.pct / total, background: s.color, opacity: active === -1 || active === i ? 1 : .3 }}
                  onMouseEnter={() => setActive(i)} onMouseLeave={() => setActive(-1)} />
              ))}
            </div>
          </>
        )}

        <div className="db-alloc__side">
          <div className="db-legend">
            {a.slices.map((s, i) => (
              <div key={i} className={`db-legend__i ${active === i ? 'is-on' : ''}`}
                onMouseEnter={() => setActive(i)} onMouseLeave={() => setActive(-1)}>
                <span className="db-legend__sq" style={{ background: s.color }} />
                <span className="db-legend__l">{s.label}</span>
                <span className="db-legend__v tabular">{s.pct}%</span>
              </div>
            ))}
          </div>
          <LinkOut href="Investment%20Insights.html">View Allocation &amp; Holdings</LinkOut>
        </div>

        {active > -1 && <AllocationTip index={active} />}
      </div>
    </Card>
  );
}

// Segment tooltip (Figma 7367:15576) — shares the chart tooltip shell.
function AllocationTip({ index }) {
  const s = DB.allocation.slices[index];
  const rows = DB.allocationAccounts(index);
  const fmt = (v) => (v >= 1e6 ? `$${(v / 1e6).toFixed(1)}M` : `$${Math.round(v / 1e3)}K`);
  return (
    <div className="db-tip db-tip--alloc">
      <div className="db-tip__hd">
        <span className="db-tip__title">
          <span className="db-tip__dot" style={{ background: s.color }} />
          {s.label}
        </span>
        <span className="db-tip__sub">
          <span>Current Share: <b className="tabular">{s.pct}%</b></span>
          <span className="tabular">{rows.length} Accounts</span>
        </span>
      </div>
      <div className="db-tip__rule" />
      <div className="db-tip__rows">
        {rows.map((r, i) => (
          <div className="db-tip__row" key={i}>
            <span className="db-tip__nm">{r.name}</span>
            <span className="db-tip__amt tabular">{fmt(r.value)}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------------- 3. Fast links ---------------- */

function FastLinkTile({ item, compact }) {
  return (
    <a className={`db-tile ${compact ? 'db-tile--compact' : ''}`} href={item.href}>
      <span className="db-tile__ic"><Icon name={item.icon} style={{ width: 18, height: 18 }} /></span>
      <span className="db-tile__txt">
        <span className="db-tile__head">
          <span className="db-tile__t">{item.title}</span>
          {item.unseen && <span className="db-status db-status--brand">Not Viewed</span>}
          <Icon name="arrow-up-right" style={{ width: 18, height: 18 }} className="db-tile__go" />
        </span>
        <span className="db-tile__d">{item.desc}</span>
      </span>
    </a>
  );
}

function FastLinks() {
  return (
    <Card className="db-fast">
      {DB.fastLinks.map((l, i) => <FastLinkTile key={i} item={l} />)}
    </Card>
  );
}

/* ---------------- 4. Accounts ---------------- */

function AccountsCard() {
  const a = DB.accounts;
  // 'add' — account creation, step one; 'table' — the full Investment Accounts
  // view. Opening Add from inside the table replaces it rather than stacking.
  const [modal, setModal] = useState(null);

  return (
    <Card className="db-accounts">
      <CardHead title="Accounts">
        <button type="button" className="db-btn" onClick={() => setModal('add')}>
          <Icon name="plus" style={{ width: 18, height: 18 }} />Add
        </button>
        <span className="db-btn__sep" />
        <button type="button" className="db-btn" onClick={() => setModal('table')}>
          View More<Icon name="maximize-2" style={{ width: 18, height: 18 }} />
        </button>
      </CardHead>

      {modal === 'add' && <AddAccountModal onClose={() => setModal(null)} />}
      {modal === 'table' && (
        <InvestmentAccountsModal onClose={() => setModal(null)} onAdd={() => setModal('add')} />
      )}

      <div className="db-metrics db-metrics--bordered">
        <Metric label="Investments Today" value={a.investmentsToday} />
        <Metric label="Net Worth Today" value={a.netWorthToday} divided />
      </div>

      <div className="db-table">
        {a.rows.map((r, i) => (
          <div className="db-row" key={i}>
            <span className="db-row__ic"><Icon name={r.icon} style={{ width: 18, height: 18 }} /></span>
            <span className="db-row__main">
              <span className="db-row__nm">{r.name}</span>
              <span className="db-row__meta">
                <span className="db-row__type">{r.type}</span>
                <StatusPill status={r.status} link={r.link} />
              </span>
            </span>
            <span className="db-row__bal tabular">{DB.money(r.balance)}</span>
          </div>
        ))}
      </div>
    </Card>
  );
}

/* ---------------- 5. Investment projections ---------------- */

const PERIODS = { '2026 – 2085': 2085, '2026 – 2060': 2060, '2026 – 2040': 2040 };

function ProjectionsCard({ tab }) {
  const p = DB.projections;
  const [period, setPeriod] = useState('2026 – 2085');
  const [view, setView] = useState('Grouped');
  const [chartType, setChartType] = useState('Line');

  // Net Worth is not yet specified as its own dataset in Figma; the prototype
  // scales the investment curves by the same flat factor the Accounts card uses
  // for Net Worth Today. Swap for real series when the Net Worth data lands.
  const scale = tab === 'Net Worth' ? DB.NET_WORTH_UPLIFT : 1;

  const lastYear = PERIODS[period];
  const legendSeries = p.legendOrder.map((k) => p.series.find((s) => s.key === k));

  let series = p.series.map((s) => ({
    ...s,
    anchors: s.anchors.map(([y, v]) => [y, v * scale]),
  }));

  if (view === 'Total') {
    const years = [];
    for (let y = p.firstYear; y <= lastYear; y++) years.push(y);
    series = [{
      key: 'total',
      label: 'Total',
      color: '#2E5FFF',
      anchors: years.filter((y) => (y - p.firstYear) % 2 === 0).map((y) => [
        y,
        p.series.reduce((sum, s) => sum + valueAt(s.anchors, y) * scale, 0),
      ]),
    }];
  }

  // Every view stacks the buckets, so the axis has to reach the tallest stacked
  // TOTAL rather than the tallest single curve — the Figma captions were traced
  // when the buckets were drawn independently from the baseline, and a stack
  // three times as tall can't wear them. The Total view plots that same sum as
  // one series, so it lands on the same axis and switching View no longer
  // rescales the plot under the user.
  const stackedMax = Math.max(...Array.from({ length: lastYear - p.firstYear + 1 },
    (_, i) => series.reduce((sum, s) => sum + valueAt(s.anchors, p.firstYear + i), 0)));

  const yMax = Math.max(5, Math.ceil(stackedMax * 1.05 / 5) * 5);
  const yTicks = [yMax, yMax * 0.75, yMax * 0.5, yMax * 0.25, p.yMin]
    .map((v) => (v === 0 ? '$0' : `$${Math.round(v * 10) / 10}M`));

  const xTicks = p.xTicks.filter((y) => y <= lastYear);
  if (xTicks[xTicks.length - 1] !== lastYear) xTicks.push(lastYear);

  return (
    <Card>
      <CardHead title="Investment projections">
        <Select label="Period:" value={period} options={Object.keys(PERIODS)} onChange={setPeriod} />
        <Select label="View:" value={view} options={['Grouped', 'Total']} onChange={setView} />
        <Select label="Chart type:" value={chartType} options={['Line', 'Bar']} onChange={setChartType} />
      </CardHead>

      <div className="db-metrics db-metrics--wide">
        {p.metrics.map((m, i) => (
          <Metric key={i} label={m.label} value={Math.round(m.value * scale)} change={m.change} divided={i > 0} />
        ))}
      </div>

      <ProjectionChart data={{ ...p, lastYear, yMax, yTicks, xTicks, series, chartType }} />

      <div className="db-chart-legend">
        {(view === 'Total' ? series : legendSeries).map((s) => (
          <span className="db-chart-legend__i" key={s.key}>
            <span className="db-chart-legend__sq" style={{ background: s.color }} />
            {s.label}
            {s.note && <span className="db-chart-legend__note">{s.note}</span>}
          </span>
        ))}
      </div>
    </Card>
  );
}

/* ---------------- 6. Bottom links ---------------- */

function BottomLinks() {
  return (
    <div className="db-bottom">
      {DB.bottomLinks.map((l, i) => <FastLinkTile key={i} item={l} compact />)}
    </div>
  );
}

/* ---------------- page ---------------- */

function App() {
  // Expanded by default and shared across pages, matching the other prototypes.
  const [sbExpanded, setSbExpanded] = useState(() => localStorage.getItem('wt-sb-expanded') !== '0');
  const [mobileOpen, setMobileOpen] = useState(false);
  const [tab, setTab] = useState('Investments');

  useEffect(() => { localStorage.setItem('wt-sb-expanded', sbExpanded ? '1' : '0'); }, [sbExpanded]);

  // Collapse the rail when the viewport can't fit it; peek-on-hover overlay.
  window.useWTAutoCollapse(sbExpanded, setSbExpanded);
  const sbHover = window.useWTHoverExpand(sbExpanded);

  return (
    <div className="app">
      <DBSidebar
        expanded={sbExpanded || sbHover}
        overlay={sbHover}
        onToggle={() => setSbExpanded((v) => !v)}
        mobileOpen={mobileOpen}
        onMobileClose={() => setMobileOpen(false)} />
      <main className="main">
        <DBHeader onMobileMenu={() => setMobileOpen(true)} />
        <div className="db-page">
          <PlanProjections />

          <div className="db-grid">
            <div className="db-grid__col">
              <AllocationCard />
              <FastLinks />
            </div>
            <div className="db-grid__cell">
              <AccountsCard />
            </div>
          </div>

          <div className="db-section">
            <div className="db-tabs" role="tablist">
              {['Investments', 'Net Worth'].map((t) => (
                <button key={t} role="tab" aria-selected={tab === t}
                  className={`db-tab ${tab === t ? 'is-on' : ''}`}
                  onClick={() => setTab(t)}>{t}</button>
              ))}
            </div>
            <ProjectionsCard tab={tab} />
          </div>

          <BottomLinks />
        </div>
      </main>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
