/* shell.jsx — orchestrator: frame chrome, progress rail, onboarding state
   machine, the handoff into a live Home, and Tweaks. */

/* ---------- status bar (from the app shell) ------------------------------- */
const StatusBar = ({ color = "var(--ink)" }) => (
  <div className="statusbar" style={{ color }}>
    <span>9:41</span>
    <div className="sb-right">
      <svg width="18" height="12" viewBox="0 0 18 12"><g fill="currentColor">
        <rect x="0" y="8" width="3" height="4" /><rect x="5" y="5" width="3" height="7" /><rect x="10" y="2" width="3" height="10" /><rect x="15" y="0" width="3" height="12" />
      </g></svg>
      <svg width="16" height="12" viewBox="0 0 16 12" fill="none" stroke="currentColor" strokeWidth="1.4"><path d="M2 4 C5 1.5 11 1.5 14 4" /><path d="M4 6.5 C6 5 10 5 12 6.5" /><circle cx="8" cy="9.5" r="0.9" fill="currentColor" stroke="none" /></svg>
      <svg width="26" height="13" viewBox="0 0 26 13"><rect x="0.5" y="0.5" width="22" height="12" rx="3" fill="none" stroke="currentColor" strokeOpacity="0.5" /><rect x="2" y="2" width="18" height="9" rx="1.5" fill="currentColor" /><rect x="23.5" y="4" width="2" height="5" rx="1" fill="currentColor" fillOpacity="0.5" /></svg>
    </div>
  </div>
);

/* ---------- progress rail ------------------------------------------------- */
const PHASES = ["Verify", "Profile", "Secure", "Connect"];
const ProgressRail = ({ phase, fill, mins, onBack, canBack }) => (
  <div style={{ flex: "none", padding: "4px 18px 12px", background: "var(--bg)" }}>
    <div style={{ display: "flex", gap: 6 }}>
      {PHASES.map((_, i) => {
        const f = i < phase ? 1 : i === phase ? fill : 0;
        return (
          <div key={i} style={{ flex: 1, height: 3, background: "var(--rule)", overflow: "hidden" }}>
            <div style={{ height: "100%", transformOrigin: "left", transform: `scaleX(${f})`, background: "var(--accent)", transition: "transform 480ms var(--ease)" }} />
          </div>
        );
      })}
    </div>
    <div style={{ display: "flex", alignItems: "center", marginTop: 9, minHeight: 18 }}>
      {canBack ? (
        <button className="press" onClick={onBack} aria-label="Back" style={{ background: "none", border: "none", padding: 0, margin: "0 8px 0 0", display: "flex", color: "var(--ink-2)", cursor: "pointer" }}>
          <Icon name="back" size={17} color="var(--ink-2)" />
        </button>
      ) : null}
      <span style={{ fontFamily: "var(--f-display)", fontSize: 10.5, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase", color: "var(--ink-2)" }}>{PHASES[phase]}</span>
      <span style={{ marginLeft: "auto", fontFamily: "var(--f-mono)", fontSize: 11, color: "var(--ink-3)" }}>≈ {mins} min</span>
    </div>
  </div>
);

/* ---------- compact approval sheet — the brand's wow ---------------------- */
const ApprovalSheet = ({ proposal: p, onApprove, onClose }) => {
  const [approving, setApproving] = useState(false);
  const go = () => { setApproving(true); setTimeout(() => onApprove(p.id), 900); };
  return (
    <>
      <div className="yo-focus-backdrop" onClick={approving ? undefined : onClose} style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)", zIndex: 300 }} />
      <div style={{ position: "absolute", left: 0, right: 0, bottom: 0, zIndex: 301, background: "var(--bg)", borderTop: "1px solid var(--accent)", maxHeight: "94%", display: "flex", flexDirection: "column", animation: "sheet-in 320ms cubic-bezier(0.16,1,0.30,1) both" }} data-screen-label="Approval">
        <div style={{ display: "flex", justifyContent: "center", paddingTop: 8, flex: "none" }}><span style={{ width: 36, height: 4, background: "var(--rule-2)", borderRadius: 999 }} /></div>
        <div className="scroll" style={{ padding: "12px 20px 0" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 7 }}>
            <span style={{ width: 6, height: 6, borderRadius: 999, background: "var(--accent)", flex: "none" }} />
            <span style={{ fontFamily: "var(--f-display)", fontSize: 10, fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--ink-3)" }}>{p.agent} · proposes</span>
          </div>
          <div style={{ fontFamily: "var(--f-display)", fontSize: 22, fontWeight: 700, letterSpacing: "-0.025em", marginTop: 9 }}>{p.title}</div>
          <div style={{ fontFamily: "var(--f-display)", fontSize: 13.5, color: "var(--ink-2)", marginTop: 7, lineHeight: 1.5 }}>{p.why}</div>

          <Eyebrow style={{ margin: "18px 0 8px" }}>The move</Eyebrow>
          <div style={{ border: "1px solid var(--rule)" }}>
            {p.legs.map((l, i) => (
              <div key={i} style={{ display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 10, alignItems: "center", padding: "11px 13px", borderBottom: i < p.legs.length - 1 ? "1px dashed var(--rule)" : "none" }}>
                <span style={{ fontFamily: "var(--f-display)", fontSize: 9.5, fontWeight: 700, letterSpacing: "0.06em", color: l[0] === "SELL" ? "var(--signal-neg)" : "var(--accent)", width: 34 }}>{l[0]}</span>
                <span style={{ fontFamily: "var(--f-display)", fontSize: 13.5, fontWeight: 600 }}>{l[1]} <span style={{ color: "var(--ink-3)", fontWeight: 500 }}>· {l[2]}</span></span>
                <span style={{ fontFamily: "var(--f-mono)", fontSize: 12.5, color: "var(--ink-2)" }}>{l[3]}</span>
              </div>
            ))}
          </div>

          <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", marginTop: 14 }}>
            <span style={{ fontFamily: "var(--f-display)", fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--ink-3)" }}>Net to you · settles {p.settles}</span>
            <Money value={p.net} size={18} weight={600} sign color={p.net >= 0 ? "var(--accent-pos)" : "var(--ink)"} />
          </div>
        </div>

        <div style={{ flex: "none", padding: "16px 20px 22px" }}>
          {/* the seam draws across at the moment of approval */}
          <div style={{ height: 1, background: "var(--accent)", opacity: 0.6, transformOrigin: "left center", transform: `scaleX(${approving ? 1 : 0})`, transition: "transform 700ms linear", marginBottom: 14 }} />
          {approving ? (
            <div style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 9, padding: "13px", color: "var(--accent)" }}>
              <LiveDot size={6} /><span style={{ fontFamily: "var(--f-display)", fontSize: 14, fontWeight: 600 }}>Executing…</span>
            </div>
          ) : (
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1.6fr", gap: 10 }}>
              <Btn kind="ghost" onClick={onClose}>Not now</Btn>
              <Btn onClick={go}><Icon name="check" size={17} color="var(--accent-ink)" /> Approve &amp; sign</Btn>
            </div>
          )}
        </div>
      </div>
    </>
  );
};

/* ---------- focus picker — the day-one "point Yoshi at something" ---------- */
const FOCI = [
  { id: "cash", icon: "swap", t: "Grow my idle cash", s: "Earn more on cash you're not using." },
  { id: "tax", icon: "receipt", t: "Stay ahead of taxes", s: "Set aside the right amount as you earn." },
  { id: "invest", icon: "trade", t: "Invest on a schedule", s: "Put money in on autopilot, on target." },
  { id: "simplify", icon: "bolt", t: "Simplify everything", s: "Steady income, bills paid, less to watch." },
];
const FocusSheet = ({ onPick, onClose }) => (
  <>
    <div className="yo-focus-backdrop" onClick={onClose} style={{ position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)", zIndex: 300 }} />
    <div style={{ position: "absolute", left: 0, right: 0, bottom: 0, zIndex: 301, background: "var(--bg)", borderTop: "1px solid var(--accent)", maxHeight: "92%", display: "flex", flexDirection: "column", animation: "sheet-in 320ms cubic-bezier(0.16,1,0.30,1) both" }} data-screen-label="Pick a focus">
      <div style={{ display: "flex", justifyContent: "center", paddingTop: 8, flex: "none" }}><span style={{ width: 36, height: 4, background: "var(--rule-2)", borderRadius: 999 }} /></div>
      <div className="scroll" style={{ padding: "12px 20px 24px" }}>
        <div style={{ fontFamily: "var(--f-display)", fontSize: 22, fontWeight: 700, letterSpacing: "-0.025em" }}>What should Yoshi focus on first?</div>
        <div style={{ fontFamily: "var(--f-display)", fontSize: 13.5, color: "var(--ink-2)", marginTop: 7, lineHeight: 1.5 }}>Pick one to start. Yoshi will draft a first move for you to approve, you can change focus anytime.</div>
        <div style={{ display: "grid", gap: 9, marginTop: 18 }}>
          {FOCI.map((f) => (
            <button key={f.id} className="press" onClick={() => onPick(f.id, f.t)} style={{ width: "100%", textAlign: "left", cursor: "pointer", display: "flex", alignItems: "center", gap: 13, padding: "14px 15px", background: "var(--bg-card)", border: "1px solid var(--rule)", borderRadius: 12 }}>
              <span style={{ width: 36, height: 36, flex: "none", borderRadius: 10, border: "1px solid var(--accent)", display: "grid", placeItems: "center", color: "var(--accent)" }}><Icon name={f.icon} size={19} color="var(--accent)" /></span>
              <span style={{ flex: 1 }}>
                <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 14.5, fontWeight: 600 }}>{f.t}</span>
                <span style={{ display: "block", fontFamily: "var(--f-display)", fontSize: 12, color: "var(--ink-3)", marginTop: 2 }}>{f.s}</span>
              </span>
              <Icon name="arrow" size={16} color="var(--ink-3)" />
            </button>
          ))}
        </div>
      </div>
    </div>
  </>
);

/* ---------- the orchestrator ---------------------------------------------- */
const STEPS = [
  { key: "welcome",     rail: false },
  { key: "verifyIntro", rail: true, phase: 0, fill: 0.5 },
  { key: "plaid",       rail: false },
  { key: "provision",   rail: false },
  { key: "success",     rail: true, phase: 0, fill: 1 },
  { key: "income",      rail: true, phase: 1, fill: 0.5 },
  { key: "checks",      rail: true, phase: 1, fill: 1 },
  { key: "security",    rail: true, phase: 2, fill: 1 },
  { key: "link",        rail: true, phase: 3, fill: 0.34 },
  { key: "funding",     rail: true, phase: 3, fill: 0.67 },
  { key: "agent",       rail: true, phase: 3, fill: 1 },
  { key: "disclosures", rail: true, phase: 3, fill: 1 },
  { key: "offToWork",   rail: false },
];
const idxOf = (k) => STEPS.findIndex((s) => s.key === k);

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "graphite",
  "accent": "#deb24e",
  "showRail": true,
  "account": "dayone"
}/*EDITMODE-END*/;

const App = () => {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const qp = new URLSearchParams(location.search);
  const startStep = qp.get("step");
  const [step, setStep] = useState(startStep && idxOf(startStep) >= 0 ? startStep : "welcome");
  const [app, setApp] = useState(qp.get("app") === "1");
  const [tab, setTab] = useState("home");
  const [overlay, setOverlay] = useState(null);
  const [toast, setToast] = useState(null);

  // flow data
  const [idv, setIdv] = useState({ phone: "", dob: "", first: "Rivka", last: "Lipson", street: "1452 Valencia St", city: "San Francisco", state: "CA", zip: "94110" });
  const [income, setIncome] = useState({ status: "Employed", company: "Northwind Labs", title2: "Product Designer", source: "Salary", incomeBand: "" });
  const [checks, setChecks] = useState({ none: false, flags: {} });
  const [funding, setFunding] = useState(null);
  const [deposit, setDeposit] = useState(() => { const d = parseInt(qp.get("deposit") || "0", 10); return Number.isFinite(d) ? d : 0; });
  const [externals, setExternals] = useState(() => {
    const a = qp.get("accts");
    if (!a) return [];
    const seed = [];
    if (/cash/.test(a)) seed.push({ inst: "Chase", instId: "chase", tint: "#1156a3", name: "Chase Total Checking", type: "Checking", mask: "••4471", bal: 14231 });
    if (/invest/.test(a)) seed.push({ inst: "Schwab", instId: "schwab", tint: "#0a7d3e", name: "Schwab Brokerage", type: "Brokerage", mask: "••9920", bal: 38400 });
    return seed;
  });
  const [agents, setAgents] = useState([]);
  const [goal, setGoal] = useState(null);

  // post-onboarding live state
  const [proposals, setProposals] = useState(PROPOSALS);
  const [completed, setCompleted] = useState(COMPLETED);

  const dark = t.palette === "graphite";
  useEffect(() => {
    const r = document.getElementById("root");
    r.setAttribute("data-palette", t.palette);
    if (t.accent) r.style.setProperty("--accent", t.accent);
  }, [t.palette, t.accent]);

  useEffect(() => { const id = setTimeout(() => document.body.classList.add("anim-ready"), 800); return () => clearTimeout(id); }, []);

  // the celebratory screen is full-bleed dark — extend it behind the status bar
  useEffect(() => {
    const r = document.getElementById("root");
    r.style.background = (!app && step === "offToWork") ? "#141310" : "";
  }, [app, step]);

  const flash = (m) => { setToast(m); setTimeout(() => setToast((x) => (x === m ? null : x)), 2400); };
  const goto = (k) => setStep(k);

  // back: previous navigable rail step (skip plaid + provision + the auto success screen)
  const back = () => {
    let i = idxOf(step) - 1;
    while (i >= 0 && (STEPS[i].key === "plaid" || STEPS[i].key === "provision" || STEPS[i].key === "success")) i--;
    if (i >= 0) setStep(STEPS[i].key);
  };

  const enter = () => { setApp(true); setTab("home"); };

  const onApproved = (id) => {
    const pr = proposals.find((x) => x.id === id);
    setProposals((ps) => ps.filter((x) => x.id !== id));
    if (pr) setCompleted((cs) => [{ id: "ex_" + id, title: pr.title, detail: pr.legs.map((l) => l[1]).join(" · "), when: "Today", net: pr.net, by: pr.agent }, ...cs]);
    setOverlay(null);
    flash("Executed · " + (pr ? pr.title : "move"));
  };

  // nav stub for the live Home — most destinations flash, proposals open for real
  const nav = useMemo(() => ({
    tab: (x) => { if (x === "home") setTab(x); else flash("That lives in the full app"); },
    studio: () => flash("Studio lives in the full app"),
    push: () => flash("Opens in the full app"),
    pop: () => {},
    sheet: () => flash("Opens in the full app"),
    closeSheet: () => setOverlay(null),
    ask: () => flash("Yoshi chat lives in the full app"),
    automation: () => flash("Opens in the full app"),
  }), []);
  const openApproval = (id) => setOverlay({ type: "approve", id });

  const cur = STEPS[idxOf(step)] || STEPS[0];
  const onboardScreens = {
    welcome:     <Welcome onNext={() => goto("verifyIntro")} />,
    verifyIntro: <VerifyIntro onNext={() => goto("plaid")} />,
    provision:   <Provisioning onDone={() => goto("success")} />,
    success:     <Success onNext={() => goto("income")} />,
    income:      <Income data={income} setData={setIncome} phone={idv.phone} onNext={() => goto("checks")} />,
    checks:      <Checks data={checks} setData={setChecks} onNext={() => goto("security")} />,
    security:    <Security onNext={() => goto("link")} />,
    link:        <Funding funding={funding} setFunding={setFunding} externals={externals} setExternals={setExternals} onNext={() => goto("funding")} onSkipToAgent={() => goto("agent")} />,
    funding:     <FundDeposit funding={funding} setFunding={setFunding} externals={externals} setExternals={setExternals} deposit={deposit} setDeposit={setDeposit} onNext={() => goto("agent")} onSkip={() => goto("agent")} />,
    agent:       <Agent agents={agents} setAgents={setAgents} onNext={() => goto("disclosures")} onSkip={() => { setAgents([]); goto("disclosures"); }} />,
    disclosures: <Disclosures onNext={() => goto("offToWork")} />,
    offToWork:   <OffToWork agents={agents} accent={t.accent} onEnter={enter} />,
  };

  // status bar color: dark celebratory screen + plaid takeover want light text
  const sbColor = (!app && (step === "offToWork" || step === "plaid")) ? "#f3f1ea" : "var(--ink)";

  return (
    <ThemeCtx.Provider value={t.palette}>
      <StatusBar color={sbColor} />

      {!app ? (
        <div className="viewport" style={{ position: "relative" }}>
          {cur.rail && t.showRail && (
            <ProgressRail phase={cur.phase} fill={cur.fill} mins={Math.max(1, Math.ceil((idxOf("agent") - idxOf(step) + 1) / 3))} onBack={back} canBack />
          )}
          <div key={step} className="tab-swap" style={{ flex: 1, minHeight: 0, display: "flex", flexDirection: "column", overflow: "hidden" }}>
            {onboardScreens[step]}
          </div>
          {step === "plaid" && (
            <PlaidIDV data={idv} setData={setIdv} onDone={() => goto("provision")} onCancel={() => goto("verifyIntro")} />
          )}
        </div>
      ) : (
        <>
          <div className="viewport" style={{ position: "relative" }}>
            {t.account === "dayone" && <IMessageBanner phone={idv.phone} />}
            <div key={tab + t.account} className="tab-swap" style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column" }}>
              {t.account === "dayone"
                ? <HomeDayOne balance={deposit} goal={goal} externals={externals} nav={nav} flash={flash}
                    onAddMoney={() => flash("Add money opens in the full app")}
                    onConnect={() => setOverlay({ type: "plaidlink" })}
                    onPickGoal={() => setOverlay({ type: "focus" })} />
                : <Home nav={nav} proposals={proposals} completed={completed} onApprove={openApproval} />}
            </div>
            {toast && <Toast msg={toast} />}
          </div>
          <TabBar tab={tab} onTab={nav.tab} />
        </>
      )}

      {/* approval overlay (works in both phases) */}
      {overlay?.type === "approve" && (proposals.find((p) => p.id === overlay.id) || PROPOSALS.find((p) => p.id === overlay.id)) && (
        <ApprovalSheet proposal={proposals.find((p) => p.id === overlay.id) || PROPOSALS.find((p) => p.id === overlay.id)}
          onApprove={onApproved} onClose={() => setOverlay(null)} />
      )}
      {!app && toast && <Toast msg={toast} />}

      {/* day-one app overlays */}
      {overlay?.type === "plaidlink" && (
        <PlaidLink mode="readonly" onClose={() => setOverlay(null)} onLinked={(accts) => { setExternals((p) => [...p, ...accts]); setOverlay(null); flash("Connected · " + accts[0].inst); }} />
      )}
      {overlay?.type === "focus" && (
        <FocusSheet onPick={(id, label) => { setGoal(id); setOverlay(null); flash("Yoshi is on it · " + label); }} onClose={() => setOverlay(null)} />
      )}

      <TweaksPanel>
        <TweakSection label="Flow" />
        <TweakToggle label="Progress rail" value={t.showRail} onChange={(v) => setTweak("showRail", v)} />
        <TweakSection label="After onboarding" />
        <TweakRadio label="Account" value={t.account} options={[{ value: "dayone", label: "Day one" }, { value: "established", label: "Established" }]} onChange={(v) => setTweak("account", v)} />
        <TweakSection label="Jump to step" />
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
          {STEPS.map((s) => (
            <button key={s.key} onClick={() => { setApp(false); setOverlay(null); setStep(s.key); }} style={{ padding: "7px 8px", cursor: "pointer", textTransform: "capitalize",
              background: !app && step === s.key ? "var(--accent)" : "transparent", color: !app && step === s.key ? "#fff" : "inherit",
              border: "1px solid rgba(125,125,125,0.3)", fontSize: 11, fontFamily: "system-ui", borderRadius: 4 }}>{s.key}</button>
          ))}
          <button onClick={() => enter()} style={{ gridColumn: "1 / -1", padding: "7px 8px", cursor: "pointer", background: app ? "var(--accent)" : "transparent", color: app ? "#fff" : "inherit", border: "1px solid rgba(125,125,125,0.3)", fontSize: 11, fontFamily: "system-ui", borderRadius: 4 }}>the app (home)</button>
        </div>
      </TweaksPanel>
    </ThemeCtx.Provider>
  );
};

const Toast = ({ msg }) => (
  <div style={{ position: "absolute", left: 16, right: 16, bottom: 0, zIndex: 350, background: "var(--terminal-fill)", color: "var(--terminal-ink)", padding: "12px 15px", display: "flex", alignItems: "center", gap: 9, animation: "count-up 240ms ease both", boxShadow: "0 8px 30px -10px rgba(0,0,0,0.5)" }}>
    <span style={{ width: 6, height: 6, borderRadius: 999, background: "var(--accent)", flex: "none" }} />
    <span style={{ fontFamily: "var(--f-display)", fontSize: 13, fontWeight: 500 }}>{msg}</span>
  </div>
);

/* tab bar (from the app shell) */
const TABS = [["home", "Home"], ["trade", "Trade"], ["chat", "Yoshi"], ["studio", "Studio"], ["accounts", "Accounts"]];
const TabBar = ({ tab, onTab }) => (
  <div className="tabbar">
    {TABS.map(([id, label]) => {
      const on = id === tab;
      if (id === "chat") {
        return (
          <button key={id} className="tab press" onClick={() => onTab(id)} style={{ overflow: "visible" }}>
            <span style={{ position: "absolute", top: -26, left: "50%", transform: "translateX(-50%)", width: 58, height: 58, borderRadius: 999, background: "var(--bg-card)", border: on ? "1.5px solid var(--accent)" : "1px solid var(--rule)", boxShadow: "0 8px 22px -8px rgba(0,0,0,0.32), 0 2px 6px -2px rgba(0,0,0,0.18)", display: "grid", placeItems: "center" }}>
              <Logo size={26} />
            </span>
            <span className="tlabel" style={{ marginTop: 34, color: on ? "var(--ink)" : "var(--ink-3)", fontWeight: on ? 700 : 500 }}>{label}</span>
          </button>
        );
      }
      return (
        <button key={id} className="tab press" onClick={() => onTab(id)}>
          {on && <span style={{ position: "absolute", top: -9, left: "50%", transform: "translateX(-50%)", width: 18, height: 2, background: "var(--accent)" }} />}
          <div style={{ position: "relative", height: 23, display: "flex", alignItems: "center" }}>
            <Icon name={id} size={23} stroke={on ? 1.7 : 1.5} color={on ? "var(--ink)" : "var(--ink-3)"} />
          </div>
          <span className="tlabel" style={{ color: on ? "var(--ink)" : "var(--ink-3)", fontWeight: on ? 700 : 500 }}>{label}</span>
        </button>
      );
    })}
  </div>
);

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