// Inveritate — Home page interactives
const { useState, useMemo, useEffect, useRef } = React;

/* ============================================================
   ALLOCATION VIS
   ============================================================ */

// Real holdings (from user) — converted to allocation %
//   Metal     £707,147
//   Property  £1,005,000
//   Bank      £34,977
//   Vehicles  £55,000
const HOLDINGS = [
  { id: "property", name: "Property",      sub: "Primary residence + 2 BTL",       value: 1005000, color: "oklch(0.55 0.06 60)",  delta: "Stable",   trend: "flat" },
  { id: "metal",    name: "Precious metal", sub: "Gold & silver bullion",          value: 707147,  color: "oklch(0.62 0.09 80)",  delta: "+102.9%",  trend: "up" },
  { id: "vehicles", name: "Vehicles",       sub: "Held for use, not appreciation", value: 55000,   color: "oklch(0.45 0.04 60)",  delta: "Depreciating", trend: "down" },
  { id: "cash",     name: "Bank & cash",    sub: "Operating reserves, multi-ccy",  value: 34977,   color: "oklch(0.5 0.05 145)",  delta: "Liquid",   trend: "flat" },
  { id: "equities", name: "Public equities", sub: "Index funds & dividend stocks",  value: 0,       color: "oklch(0.42 0.08 250)", delta: "0%",       trend: "flat", planned: true },
  { id: "private",  name: "Private capital", sub: "PE / VC / cash-flowing biz",     value: 0,       color: "oklch(0.4 0.07 320)",  delta: "0%",       trend: "flat", planned: true },
];

const TOTAL = HOLDINGS.reduce((s, h) => s + h.value, 0);

function AllocationDonut({ active, onHover }) {
  const size = 360;
  const r = 130;
  const stroke = 28;
  const cx = size / 2;
  const cy = size / 2;
  const circ = 2 * Math.PI * r;

  let cum = 0;
  const segs = HOLDINGS.filter(h => h.value > 0).map(h => {
    const frac = h.value / TOTAL;
    const len = circ * frac;
    const offset = -circ * cum;
    cum += frac;
    return { ...h, len, offset, frac };
  });

  return (
    <svg viewBox={`0 0 ${size} ${size}`} style={{ width: "100%", maxWidth: 360, height: "auto", display: "block", margin: "0 auto" }}>
      {/* paper inner ring */}
      <circle cx={cx} cy={cy} r={r} fill="none" stroke="oklch(0.93 0.012 75)" strokeWidth={stroke} />
      {segs.map(s => (
        <circle
          key={s.id}
          cx={cx} cy={cy} r={r}
          fill="none"
          stroke={s.color}
          strokeWidth={active === s.id ? stroke + 6 : stroke}
          strokeDasharray={`${s.len - 2} ${circ}`}
          strokeDashoffset={s.offset}
          transform={`rotate(-90 ${cx} ${cy})`}
          style={{ transition: "stroke-width .2s, opacity .2s", cursor: "pointer", opacity: active && active !== s.id ? 0.35 : 1 }}
          onMouseEnter={() => onHover(s.id)}
          onMouseLeave={() => onHover(null)}
        />
      ))}
      {/* tick marks at 25/50/75% */}
      {[0.25, 0.5, 0.75].map((p, i) => {
        const a = -Math.PI / 2 + p * 2 * Math.PI;
        const x1 = cx + Math.cos(a) * (r + stroke / 2 + 4);
        const y1 = cy + Math.sin(a) * (r + stroke / 2 + 4);
        const x2 = cx + Math.cos(a) * (r + stroke / 2 + 12);
        const y2 = cy + Math.sin(a) * (r + stroke / 2 + 12);
        return <line key={i} x1={x1} y1={y1} x2={x2} y2={y2} stroke="oklch(0.78 0.012 60)" strokeWidth={1} />;
      })}
    </svg>
  );
}

function HoldingsSection() {
  const [active, setActive] = useState(null);
  const a = HOLDINGS.find(h => h.id === active);
  const totalLive = HOLDINGS.reduce((s, h) => s + h.value, 0);
  const pct = (v) => ((v / totalLive) * 100);
  const fmt = (v) => v < 10 ? v.toFixed(1) : v.toFixed(0);

  return (
    <div className="holdings-wrap">
      <div className="alloc-list">
        {HOLDINGS.map(h => {
          const p = pct(h.value);
          return (
            <div
              key={h.id}
              className={`alloc-row ${active === h.id ? "active" : ""}`}
              onMouseEnter={() => setActive(h.id)}
              onMouseLeave={() => setActive(null)}
            >
              <span className="swatch" style={{ background: h.color, opacity: h.planned ? 0.3 : 1, border: h.planned ? "1px dashed oklch(0.55 0.012 60)" : "none" }}></span>
              <div className="name">
                {h.name}
                {h.planned && <span style={{ marginLeft: 8, fontSize: 11, fontFamily: "var(--mono)", letterSpacing: "0.1em", color: "var(--ink-mute)", textTransform: "uppercase" }}>· planned</span>}
                <span className="sub">{h.sub}</span>
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="pct">{fmt(p)}%</div>
                <div className={`delta ${h.trend === "up" ? "up" : h.trend === "down" ? "down" : ""}`}>{h.delta}</div>
              </div>
            </div>
          );
        })}
        <div style={{ marginTop: 24, fontFamily: "var(--mono)", fontSize: 11, letterSpacing: "0.05em", color: "var(--ink-mute)" }}>
          Last reconciled: 04 May 2026 · Held in trust · Updated quarterly
        </div>
      </div>

      <div className="alloc-vis">
        <div className="vis-frame">
          <div className="legend">
            <span>fig. 01</span>
            <span>by allocation</span>
          </div>
          <AllocationDonut active={active} onHover={setActive} />
          <div className="center-readout">
            <div className="big">{a ? `${fmt(pct(a.value))}%` : "96%"}</div>
            <div className="ttl">{a ? a.name : "Property + metal"}</div>
            <div className="note">
              {a ? (a.planned ? "A category we intend to enter — not held today." : a.sub) : "Two costumes. One bet. The work of the next decade is to change this picture."}
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

const holdingsRoot = ReactDOM.createRoot(document.getElementById("holdings-app"));
holdingsRoot.render(<HoldingsSection />);

/* ============================================================
   COMPOUND CALCULATOR
   ============================================================ */

function fmtMoney(n) {
  if (n >= 1e6) return "£" + (n / 1e6).toFixed(2) + "m";
  if (n >= 1e3) return "£" + Math.round(n / 1e3).toLocaleString() + "k";
  return "£" + Math.round(n).toLocaleString();
}

function CompoundCalc() {
  const [monthly, setMonthly] = useState(200);
  const [years, setYears] = useState(30);
  const [rate, setRate] = useState(7);

  const result = useMemo(() => {
    const r = rate / 100 / 12;
    const n = years * 12;
    const fv = monthly * ((Math.pow(1 + r, n) - 1) / r);
    const contrib = monthly * n;
    const interest = fv - contrib;
    return { fv, contrib, interest };
  }, [monthly, years, rate]);

  const chartData = useMemo(() => {
    const points = [];
    const r = rate / 100 / 12;
    for (let m = 0; m <= years * 12; m++) {
      const fv = m === 0 ? 0 : monthly * ((Math.pow(1 + r, m) - 1) / r);
      const contrib = monthly * m;
      points.push({ m, fv, contrib });
    }
    return points;
  }, [monthly, years, rate]);

  // SVG
  const W = 320, H = 100;
  const maxY = Math.max(...chartData.map(p => p.fv));
  const path = chartData.map((p, i) => {
    const x = (i / (chartData.length - 1)) * W;
    const y = H - (p.fv / maxY) * H;
    return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(" ");
  const contribPath = chartData.map((p, i) => {
    const x = (i / (chartData.length - 1)) * W;
    const y = H - (p.contrib / maxY) * H;
    return `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(" ");

  return (
    <div className="calc-frame">
      <div style={{ fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--ink-mute)", marginBottom: 18 }}>
        Compound machine · v1
      </div>

      <div className="calc-row">
        <label>Saved each month</label>
        <span className="val">£{monthly}</span>
        <input type="range" min="50" max="2000" step="50" value={monthly} onChange={(e) => setMonthly(+e.target.value)} style={{ gridColumn: "1 / -1" }} />
      </div>

      <div className="calc-row">
        <label>Years patient</label>
        <span className="val">{years} yrs</span>
        <input type="range" min="5" max="50" step="1" value={years} onChange={(e) => setYears(+e.target.value)} style={{ gridColumn: "1 / -1" }} />
      </div>

      <div className="calc-row">
        <label>Real annual return</label>
        <span className="val">{rate.toFixed(1)}%</span>
        <input type="range" min="2" max="12" step="0.5" value={rate} onChange={(e) => setRate(+e.target.value)} style={{ gridColumn: "1 / -1" }} />
      </div>

      {/* tiny chart */}
      <div style={{ marginTop: 24 }}>
        <svg viewBox={`0 0 ${W} ${H}`} style={{ width: "100%", height: 110, display: "block" }}>
          <path d={`${path} L${W},${H} L0,${H} Z`} fill="oklch(0.52 0.09 40 / 0.12)" />
          <path d={contribPath} fill="none" stroke="oklch(0.55 0.012 60)" strokeWidth={1} strokeDasharray="3 3" />
          <path d={path} fill="none" stroke="var(--accent)" strokeWidth={1.5} />
        </svg>
        <div style={{ display: "flex", justifyContent: "space-between", fontFamily: "var(--mono)", fontSize: 10, color: "var(--ink-mute)", marginTop: 6, letterSpacing: "0.05em" }}>
          <span>year 0</span>
          <span>year {years}</span>
        </div>
      </div>

      <div className="calc-result">
        <div className="ttl">Future value, in today's money</div>
        <div className="big">{fmtMoney(result.fv)}</div>
        <div className="note">
          You contribute <b style={{ fontStyle: "normal", color: "var(--ink)" }}>{fmtMoney(result.contrib)}</b>. The world contributes <b style={{ fontStyle: "normal", color: "var(--accent)" }}>{fmtMoney(result.interest)}</b>.
        </div>
      </div>
    </div>
  );
}

const calcRoot = ReactDOM.createRoot(document.getElementById("calc-app"));
calcRoot.render(<CompoundCalc />);

/* ============================================================
   FAMILY GATE
   ============================================================ */

function Gate() {
  const [unlocked, setUnlocked] = useState(false);
  const [pwd, setPwd] = useState("");
  const [err, setErr] = useState(false);

  const submit = (e) => {
    e.preventDefault();
    if (pwd.toLowerCase() === "veritas") {
      setUnlocked(true);
      setErr(false);
    } else {
      setErr(true);
    }
  };

  if (unlocked) {
    return (
      <div className="gate-grid">
        <div>
          <h3 style={{ fontSize: 28, marginBottom: 12 }}>Welcome home.</h3>
          <p style={{ color: "var(--ink-soft)", fontSize: 17, lineHeight: 1.6 }}>
            This is the live read of the workbook — real valuations, sourced from custody statements, bank feeds, and the LBMA spot. Below is a preview of the dashboard the family sees inside.
          </p>
          <p style={{ marginTop: 16, fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-mute)", letterSpacing: "0.05em" }}>
            Last sync: 04 May 2026 · 09:14 BST · Source: Veritas Workbook
          </p>
          <button onClick={() => { setUnlocked(false); setPwd(""); }} className="btn ghost" style={{ marginTop: 24 }}>
            Lock the door
          </button>
        </div>

        <div className="vault">
          <h4>Veritas Workbook · Live</h4>
          <div style={{ marginBottom: 20, paddingBottom: 16, borderBottom: "1px solid oklch(0.32 0.012 60)" }}>
            <div style={{ fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.18em", color: "oklch(0.6 0.005 80)", textTransform: "uppercase" }}>Total gross assets</div>
            <div style={{ fontFamily: "var(--serif)", fontSize: 38, color: "var(--paper)", letterSpacing: "-0.02em", marginTop: 6 }}>£1,802,124</div>
            <div style={{ fontFamily: "var(--mono)", fontSize: 12, color: "oklch(0.78 0.04 145)", marginTop: 4 }}>+1.4% this quarter · Excellent</div>
          </div>

          <div className="vault-rows">
            <div className="vault-row">
              <div className="icon">P</div>
              <div className="name">Property<span className="meta">3 properties · primary + 2 BTL</span></div>
              <div className="pct">55.8%</div>
              <div className="delta">£1,005,000</div>
            </div>
            <div className="vault-row">
              <div className="icon">M</div>
              <div className="name">Precious metal<span className="meta">Gold & silver bullion</span></div>
              <div className="pct">39.2%</div>
              <div className="delta" style={{ color: "oklch(0.78 0.04 145)" }}>+102.9%</div>
            </div>
            <div className="vault-row">
              <div className="icon">V</div>
              <div className="name">Vehicles<span className="meta">Held for use</span></div>
              <div className="pct">3.1%</div>
              <div className="delta">£55,000</div>
            </div>
            <div className="vault-row">
              <div className="icon">£</div>
              <div className="name">Bank & cash<span className="meta">Multi-currency</span></div>
              <div className="pct">1.9%</div>
              <div className="delta">£34,977</div>
            </div>
          </div>

          <div className="vault-summary">
            <div className="item">
              <div className="k">Liquid</div>
              <div className="v">£34,977</div>
            </div>
            <div className="item">
              <div className="k">Liabilities</div>
              <div className="v" style={{ color: "oklch(0.92 0.005 80)" }}>£162,000</div>
            </div>
            <div className="item">
              <div className="k">Net worth</div>
              <div className="v">£1,640,124</div>
            </div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="gate-grid">
      <div>
        <h3 style={{ fontSize: 28, marginBottom: 12 }}>One password. One family.</h3>
        <p style={{ color: "var(--ink-soft)", fontSize: 17, lineHeight: 1.6, maxWidth: 480 }}>
          The family side is where the actual ledger lives — current valuations, the running decision log, working notes I'm not yet ready to publish, and the workbook I'm building for our own use. You don't need an account. You need the password we agreed on.
        </p>
        <ul style={{ listStyle: "none", padding: 0, marginTop: 24, fontFamily: "var(--sans)", fontSize: 14, color: "var(--ink-soft)" }}>
          <li style={{ padding: "8px 0", borderBottom: "1px solid var(--rule)" }}>· Live valuations across all four asset classes</li>
          <li style={{ padding: "8px 0", borderBottom: "1px solid var(--rule)" }}>· Quarterly net-worth reconciliation</li>
          <li style={{ padding: "8px 0", borderBottom: "1px solid var(--rule)" }}>· Liabilities, liquidity, and the buffer I keep secret</li>
          <li style={{ padding: "8px 0" }}>· Notes I haven't decided to publish yet</li>
        </ul>
      </div>

      <form className="gate-form" onSubmit={submit}>
        <h3>Family area</h3>
        <p>Enter the password we agreed on at Sunday lunch.</p>
        <div className="input-row">
          <input
            type="password"
            placeholder="• • • • • • •"
            value={pwd}
            onChange={(e) => { setPwd(e.target.value); setErr(false); }}
            autoComplete="off"
          />
          <button type="submit">Enter →</button>
        </div>
        <div className={`gate-hint ${err ? "gate-error" : ""}`}>
          {err ? "Not the one. Try again — case doesn't matter." : "Hint: the trust's name. Lowercase is fine."}
        </div>
      </form>
    </div>
  );
}

const gateRoot = ReactDOM.createRoot(document.getElementById("gate-app"));
gateRoot.render(<Gate />);

// "Family area" nav button → scroll to gate
document.getElementById("open-gate")?.addEventListener("click", (e) => {
  e.preventDefault();
  const el = document.getElementById("gate");
  if (el) {
    const y = el.getBoundingClientRect().top + window.pageYOffset - 80;
    window.scrollTo({ top: y, behavior: "smooth" });
  }
});
