/* basket.jsx — "Build a basket" (web Studio).
   Public-style generated assets, seam-native: describe a thesis in plain
   English, Yoshi composes a weighted basket from the market universe,
   backtests it against the S&P, and the output is a PROPOSAL you approve.
   Rendered as a page beside the persistent chat (overlay type "basket"). */

/* ---- canned generation: thesis keywords → curated, capped weights -------- */
const BASKET_RECIPES = [
  { match: /ai|chip|infra|compute|semiconductor|data center/i, name: "AI infrastructure",
    note: "Compute, platforms, and the index ballast behind the buildout.",
    picks: [["nvda", 15], ["msft", 14], ["amd", 13], ["googl", 12], ["meta", 11], ["qqq", 15], ["vti", 12], ["aapl", 8]],
    ret1: 31.4, ret5: 162, vol: 0.020, yield_: 0.6 },
  { match: /dividend|income|defensive|stable|safe/i, name: "Dividend tilt",
    note: "Broad market core with a cash-flow lean. Lower drawdown, lower ceiling.",
    picks: [["voo", 15], ["vti", 15], ["spy", 14], ["aapl", 13], ["msft", 13], ["googl", 10], ["amzn", 10], ["meta", 10]],
    ret1: 17.8, ret5: 96, vol: 0.011, yield_: 1.9 },
  { match: /crypto|bitcoin|btc|eth|digital|coin/i, name: "Digital assets plus",
    note: "Majors-weighted crypto with equity rails exposure. Expect swings.",
    picks: [["btc", 15], ["eth", 14], ["sol", 12], ["coin", 13], ["qqq", 15], ["vti", 15], ["nvda", 8], ["msft", 8]],
    ret1: 58.2, ret5: 240, vol: 0.034, yield_: 0.1 },
  { match: /.*/, name: "Balanced growth",
    note: "Index core, quality compounders on top. The do-it-once portfolio.",
    picks: [["vti", 15], ["voo", 15], ["qqq", 13], ["msft", 12], ["aapl", 12], ["googl", 11], ["amzn", 11], ["nvda", 11]],
    ret1: 22.6, ret5: 118, vol: 0.014, yield_: 1.2 },
];

const EXAMPLE_THESES = [
  "AI infrastructure, nothing over 15%",
  "Dividend-leaning core I never touch",
  "Crypto majors with some index ballast",
];

const basketFromThesis = (thesis) => {
  const r = BASKET_RECIPES.find((x) => x.match.test(thesis)) || BASKET_RECIPES[BASKET_RECIPES.length - 1];
  const holdings = r.picks.map(([id, w]) => {
    const m = MARKET.find((x) => x.id === id);
    return m ? { id: m.id, ticker: m.ticker, name: m.name, last: m.last, weight: w } : null;
  }).filter(Boolean);
  return { ...r, thesis, holdings, cap: Math.max(...r.picks.map((p) => p[1])) };
};

/* ---- backtest chart: basket vs S&P, rebased to 0% ------------------------- */
const BasketBacktest = ({ basket, range }) => {
  const len = range === "5Y" ? 64 : 52;
  const ret = range === "5Y" ? basket.ret5 : basket.ret1;
  const spxRet = range === "5Y" ? 84 : 16;
  const seed = basket.name.length * 97 + len;
  const bSeries = useMemo(() => series(seed, len, 100, 100 * (1 + ret / 100), basket.vol), [seed, len, ret]);
  const sSeries = useMemo(() => series(seed + 7, len, 100, 100 * (1 + spxRet / 100), 0.011), [seed, len, spxRet]);
  const W = 560, H = 190, padY = 14;
  const pct = (arr, i) => (arr[i] / arr[0] - 1) * 100;
  let lo = 0, hi = 0;
  for (let i = 0; i < len; i++) { lo = Math.min(lo, pct(bSeries, i), pct(sSeries, i)); hi = Math.max(hi, pct(bSeries, i), pct(sSeries, i)); }
  const rng = (hi - lo) || 1;
  const x = (i) => i / (len - 1) * W;
  const y = (p) => padY + (1 - (p - lo) / rng) * (H - padY * 2);
  const line = (arr) => arr.map((_, i) => `${i ? "L" : "M"}${x(i).toFixed(1)},${y(pct(arr, i)).toFixed(1)}`).join(" ");
  return (
    <div>
      <svg width="100%" viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ display: "block", overflow: "visible" }}>
        <line x1="0" y1={y(0)} x2={W} y2={y(0)} stroke="var(--rule-2)" strokeWidth="1" strokeDasharray="2 3" vectorEffect="non-scaling-stroke" />
        <path d={line(sSeries)} fill="none" stroke="var(--alloc-cash)" strokeWidth="1.4" strokeDasharray="4 3" strokeLinejoin="round" vectorEffect="non-scaling-stroke" />
        <path d={`${line(bSeries)} L${W},${H} L0,${H} Z`} fill="var(--chart-line)" opacity="0.08" />
        <path d={line(bSeries)} fill="none" stroke="var(--chart-line)" strokeWidth="1.9" strokeLinejoin="round" vectorEffect="non-scaling-stroke" />
        <circle cx={x(len - 1)} cy={y(pct(bSeries, len - 1))} r="3.2" fill="var(--chart-line)" />
      </svg>
      <div style={{ display: "flex", gap: 16, marginTop: 8 }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--f-display)", fontSize: 11, fontWeight: 600, color: "var(--ink-2)" }}>
          <span style={{ width: 16, borderTop: "2px solid var(--chart-line)" }} /> {basket.name}
        </span>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 6, fontFamily: "var(--f-display)", fontSize: 11, fontWeight: 600, color: "var(--ink-2)" }}>
          <span style={{ width: 16, borderTop: "2px dashed var(--alloc-cash)" }} /> S&amp;P 500
        </span>
      </div>
    </div>
  );
};

const BasketStat = ({ label, value, color }) => (
  <div style={{ padding: "10px 12px", border: "1px solid var(--rule)", background: "var(--bg-card)" }}>
    <div style={{ fontFamily: "var(--f-display)", fontSize: 9.5, fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-3)" }}>{label}</div>
    <div style={{ fontFamily: "var(--f-mono)", fontSize: 15, fontWeight: 600, marginTop: 4, fontVariantNumeric: "tabular-nums", color: color || "var(--ink)" }}>{value}</div>
  </div>
);

/* ---- the flow ------------------------------------------------------------- */
const BasketStudio = ({ onClose, nav, onPropose, onReview }) => {
  const [thesis, setThesis] = useState("");
  const [phase, setPhase] = useState("input"); // input | generating | result | proposed
  const [basket, setBasket] = useState(null);
  const [range, setRange] = useState("1Y");
  const [amt, setAmt] = useState("5,000");
  const [proposedId, setProposedId] = useState(null);
  const amtNum = parseFloat(String(amt).replace(/[^0-9.]/g, "")) || 0;

  const generate = (text) => {
    const t = (text != null ? text : thesis).trim();
    if (!t) return;
    setThesis(t);
    setPhase("generating");
    setTimeout(() => { setBasket(basketFromThesis(t)); setPhase("result"); }, 1300);
  };
  const propose = () => {
    if (!basket || !amtNum) return;
    const id = onPropose(basket, amtNum);
    setProposedId(id);
    setPhase("proposed");
  };

  const ret = basket ? (range === "5Y" ? basket.ret5 : basket.ret1) : 0;
  const spx = range === "5Y" ? 84 : 16;
  const dd = basket ? -(basket.vol * 520).toFixed(1) : 0;

  return (
    <div className="push-enter" style={{ position: "absolute", inset: 0, zIndex: 320, background: "var(--bg)", display: "flex" }} data-screen-label="Build a basket">
      {/* LEFT — thesis in, holdings out */}
      <div style={{ flex: "1 1 0", minWidth: 300, maxWidth: 750, position: "relative", display: "flex", flexDirection: "column", minHeight: 0, padding: "0 14px", boxSizing: "border-box", borderRight: "1px solid var(--rule)" }}>
        <div style={{ flex: "none", padding: "26px 20px 0" }}>
          <span style={{ fontFamily: "var(--f-display)", fontSize: 21, fontWeight: 700, letterSpacing: "-0.025em" }}>Build a basket</span>
          <p style={{ fontFamily: "var(--f-display)", fontSize: 12.5, color: "var(--ink-2)", margin: "6px 0 0", lineHeight: 1.5 }}>Describe a thesis. Yoshi composes a weighted basket, backtests it, and drafts the buy for your approval.</p>
        </div>
        <div className="scroll" style={{ padding: "14px 20px 24px" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "12px 13px", background: "var(--bg-2)", border: `1px solid ${phase === "input" ? "var(--accent)" : "var(--rule-2)"}`, borderRadius: 12 }}>
            <Icon name="bulb" size={16} color="var(--ink-3)" stroke={1.6} style={{ flex: "none" }} />
            <input value={thesis} onChange={(e) => setThesis(e.target.value)} onKeyDown={(e) => { if (e.key === "Enter") generate(); }}
              placeholder="e.g. AI infrastructure, dividend-tilted, nothing over 15%"
              style={{ flex: 1, minWidth: 0, border: "none", background: "transparent", outline: "none", color: "var(--ink)", fontFamily: "var(--f-display)", fontSize: 13.5 }} />
            <button className="press" onClick={() => generate()} disabled={!thesis.trim()}
              style={{ flex: "none", background: thesis.trim() ? "var(--accent)" : "var(--rule-2)", color: thesis.trim() ? "var(--accent-ink)" : "var(--ink-3)", border: "none", borderRadius: 9, padding: "7px 13px", fontFamily: "var(--f-display)", fontSize: 12, fontWeight: 600, cursor: "pointer" }}>Generate</button>
          </div>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 7, marginTop: 10 }}>
            {EXAMPLE_THESES.map((q) => (
              <button key={q} className="press" onClick={() => generate(q)} style={{ flex: "none", padding: "7px 12px", borderRadius: 999, background: "color-mix(in srgb, var(--ink) 8%, var(--bg-2))", border: "none", fontFamily: "var(--f-display)", fontSize: 12, fontWeight: 500, color: "var(--ink)", cursor: "pointer" }}>{q}</button>
            ))}
          </div>

          {phase === "generating" &&
          <div style={{ display: "flex", flexDirection: "column", alignItems: "center", padding: "54px 0 30px" }}>
            <div style={{ width: 64, height: 64, display: "grid", placeItems: "center", background: "color-mix(in srgb, var(--accent) 13%, var(--bg-card))", border: "1px solid var(--accent)", animation: "yo-blob-morph 7s ease-in-out infinite, yo-blob-breathe 3.2s ease-in-out infinite" }}>
              <Logo size={26} />
            </div>
            <div style={{ fontFamily: "var(--f-display)", fontSize: 13, fontWeight: 600, marginTop: 16 }}>Composing your basket…</div>
            <div style={{ fontFamily: "var(--f-display)", fontSize: 11.5, color: "var(--ink-3)", marginTop: 5 }}>Screening the universe against your thesis and caps.</div>
          </div>}

          {(phase === "result" || phase === "proposed") && basket &&
          <>
            <div style={{ marginTop: 20, display: "flex", alignItems: "baseline", gap: 9 }}>
              <span style={{ fontFamily: "var(--f-display)", fontSize: 16, fontWeight: 700, letterSpacing: "-0.015em", flex: 1 }}>{basket.name}</span>
              <button className="press" onClick={() => generate()} style={{ background: "none", border: "none", padding: 0, cursor: "pointer", fontFamily: "var(--f-display)", fontSize: 11.5, fontWeight: 600, color: "var(--accent)" }}>Regenerate</button>
            </div>
            <p style={{ fontFamily: "var(--f-display)", fontSize: 12, color: "var(--ink-2)", margin: "4px 0 0", lineHeight: 1.5 }}>{basket.note} No single name above {basket.cap}%.</p>
            <div style={{ marginTop: 12, border: "1px solid var(--rule-2)", borderRadius: 12, background: "var(--bg-card)", overflow: "hidden" }}>
              {basket.holdings.map((h, i) => (
                <div key={h.id} style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 13px", borderTop: i ? "1px solid var(--rule)" : "none" }}>
                  <span style={{ fontFamily: "var(--f-display)", fontSize: 13, fontWeight: 700, width: 50, flex: "none" }}>{h.ticker}</span>
                  <span style={{ fontFamily: "var(--f-display)", fontSize: 11.5, color: "var(--ink-3)", flex: 1, minWidth: 0, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{h.name}</span>
                  <div style={{ flex: "none", width: 90, height: 4, background: "var(--bg-2)", borderRadius: 999 }}>
                    <div style={{ width: (h.weight / basket.cap * 100) + "%", height: "100%", background: "var(--accent)", borderRadius: 999 }} />
                  </div>
                  <span style={{ flex: "none", width: 38, textAlign: "right", fontFamily: "var(--f-mono)", fontSize: 12, fontVariantNumeric: "tabular-nums" }}>{h.weight}%</span>
                </div>
              ))}
            </div>
          </>}
        </div>
      </div>

      {/* RIGHT — backtest + propose */}
      <div style={{ flex: "1 1 0", minWidth: 300, maxWidth: 540, position: "relative", display: "flex", flexDirection: "column", minHeight: 0 }}>
        <button className="press" onClick={onClose} aria-label="Close" style={{ position: "absolute", top: 12, right: 16, zIndex: 30, background: "none", border: "none", display: "flex", color: "var(--ink-3)", cursor: "pointer", padding: 4 }}><Icon name="close" size={19} /></button>
        <div className="scroll" style={{ padding: "26px 36px 24px 20px" }}>
          {!basket || phase === "generating" || phase === "input" ? (
            <div style={{ display: "grid", placeItems: "center", minHeight: 360 }}>
              <div style={{ textAlign: "center", maxWidth: 280 }}>
                <div style={{ width: 48, height: 48, margin: "0 auto", borderRadius: 999, border: "1px solid var(--rule-2)", display: "grid", placeItems: "center", color: "var(--ink-3)" }}><Icon name="chart" size={22} stroke={1.6} /></div>
                <div style={{ fontFamily: "var(--f-display)", fontSize: 16, fontWeight: 600, marginTop: 15, letterSpacing: "-0.01em" }}>Backtest lands here</div>
                <div style={{ fontFamily: "var(--f-display)", fontSize: 13, color: "var(--ink-3)", marginTop: 7, lineHeight: 1.55 }}>Generate a basket and you'll see how it would have run against the S&amp;P, before any money moves.</div>
              </div>
            </div>
          ) : phase === "proposed" ? (
            <div style={{ display: "grid", placeItems: "center", minHeight: 380 }}>
              <div style={{ textAlign: "center", maxWidth: 300 }}>
                <div style={{ width: 52, height: 52, margin: "0 auto", borderRadius: 999, background: "color-mix(in srgb, var(--accent-pos) 14%, transparent)", display: "grid", placeItems: "center", color: "var(--accent-pos)" }}><Icon name="check" size={24} stroke={2} /></div>
                <div style={{ fontFamily: "var(--f-display)", fontSize: 17, fontWeight: 700, marginTop: 16, letterSpacing: "-0.015em" }}>Proposal drafted</div>
                <div style={{ fontFamily: "var(--f-display)", fontSize: 13, color: "var(--ink-2)", marginTop: 8, lineHeight: 1.55 }}>{usd(amtNum, 0)} into "{basket.name}" is waiting in Needs you. Nothing moves until you approve it.</div>
                <Btn full onClick={() => onReview(proposedId)} style={{ marginTop: 16 }}>Review proposal <Icon name="arrow" size={15} color="var(--accent-ink)" /></Btn>
              </div>
            </div>
          ) : (
            <>
              <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <Eyebrow style={{ flex: 1 }}>Backtest · vs S&amp;P 500</Eyebrow>
                <div style={{ display: "flex", gap: 2 }}>
                  {["1Y", "5Y"].map((r) => {
                    const on = r === range;
                    return <button key={r} className="press" onClick={() => setRange(r)} style={{ padding: "4px 10px", background: on ? "var(--bg-2)" : "transparent", border: "none", borderRadius: 7, fontFamily: "var(--f-mono)", fontSize: 11, fontWeight: on ? 700 : 500, color: on ? "var(--ink)" : "var(--ink-3)", cursor: "pointer" }}>{r}</button>;
                  })}
                </div>
              </div>
              <div style={{ marginTop: 10 }}>
                <BasketBacktest basket={basket} range={range} />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8, marginTop: 14 }}>
                <BasketStat label={"Return · " + range} value={`+${ret.toFixed(1)}%`} color="var(--accent-pos)" />
                <BasketStat label="vs S&P 500" value={`${ret - spx >= 0 ? "+" : "−"}${Math.abs(ret - spx).toFixed(1)} pts`} color={ret - spx >= 0 ? "var(--accent-pos)" : "var(--signal-neg)"} />
                <BasketStat label="Max drawdown" value={`${dd}%`} color="var(--signal-neg)" />
                <BasketStat label="Yield" value={`${basket.yield_.toFixed(1)}%`} />
              </div>
              <div style={{ fontFamily: "var(--f-display)", fontSize: 10.5, color: "var(--ink-3)", marginTop: 8, lineHeight: 1.5 }}>Simulated against historical prices. Past performance doesn't guarantee future results.</div>

              <div style={{ marginTop: 20, borderTop: "1px solid var(--rule)", paddingTop: 16 }}>
                <Eyebrow>Fund it</Eyebrow>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginTop: 9, padding: "11px 13px", background: "var(--bg-card)", border: "1px solid var(--rule-2)", borderRadius: 12 }}>
                  <span style={{ fontFamily: "var(--f-mono)", fontSize: 16, color: "var(--ink-3)" }}>$</span>
                  <input value={amt} onChange={(e) => setAmt(e.target.value)} style={{ flex: 1, minWidth: 0, border: "none", background: "transparent", outline: "none", color: "var(--ink)", fontFamily: "var(--f-mono)", fontSize: 16, fontVariantNumeric: "tabular-nums" }} />
                  {["1,000", "5,000", "10,000"].map((q) => (
                    <button key={q} className="press" onClick={() => setAmt(q)} style={{ flex: "none", padding: "4px 9px", borderRadius: 999, background: "color-mix(in srgb, var(--ink) 8%, var(--bg-2))", border: "none", fontFamily: "var(--f-mono)", fontSize: 10.5, color: "var(--ink-2)", cursor: "pointer" }}>${q}</button>
                  ))}
                </div>
                <Btn full disabled={!amtNum} onClick={propose} style={{ marginTop: 12 }}>Propose the buy <Icon name="arrow" size={15} color="var(--accent-ink)" /></Btn>
                <div style={{ display: "flex", gap: 8, alignItems: "flex-start", marginTop: 12, padding: "9px 11px", background: "var(--bg-2)" }}>
                  <Icon name="shield" size={14} color="var(--ink-3)" stroke={1.5} style={{ marginTop: 1, flex: "none" }} />
                  <span style={{ fontFamily: "var(--f-display)", fontSize: 10.5, color: "var(--ink-3)", lineHeight: 1.45 }}>Agents propose. You approve. The buy lands in Needs you, weighted exactly as shown.</span>
                </div>
              </div>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

window.BasketStudio = BasketStudio;
