/* app.jsx, the shell. Onboarding → tabbed app. Owns navigation (tab +
   push stack + overlays), proposal state, theme, status bar, tab bar. */

const TABS = [
  ["home", "Home"], ["trade", "Trade"], ["chat", "Yoshi"], ["studio", "Studio"], ["accounts", "Accounts"],
];

const StatusBar = () => (
  <div className="statusbar">
    <span>9:41</span>
    <div className="sb-right">
      {/* signal */}
      <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>
      {/* wifi */}
      <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>
      {/* battery */}
      <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>
);
window.StatusBar = StatusBar;

const TabBar = ({ tab, onTab, onTrade }) => (
  <div className="tabbar">
    {TABS.map(([id, label, icon]) => {
      const on = id === tab;

      /* Center "Yoshi" tab, a raised floating circle that pokes above the bar. */
      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>
        );
      }

      /* "Trade" is a first-class destination tab — rendered in the viewport so
         the tab bar persists (handled by the default branch below). */

      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={icon || 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>
);

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>
);

const App = () => {
  const [onboarded, setOnboarded] = useState(() => localStorage.getItem("yoshi_onboarded") === "1");
  const [palette, setPaletteState] = useState(() => localStorage.getItem("yoshi_palette") || "graphite");
  const [tab, setTab] = useState("home");
  const [stack, setStack] = useState([]);
  const [overlay, setOverlay] = useState(null);
  const [proposals, setProposals] = useState(PROPOSALS);
  useEffect(() => { window.setBellCount && window.setBellCount(proposals.length); }, [proposals]);
  const [completed, setCompleted] = useState(COMPLETED);
  const [toast, setToast] = useState(null);
  const [chatInject, setChatInject] = useState(null);
  const [studioView, setStudioView] = useState(null);
  // forked proposal threads, kept for context across the review→chat→revise loop
  const [threads, setThreads] = useState({});       // { [tid]: { id, msgs } }
  const [extraProposals, setExtraProposals] = useState([]); // revised proposals minted in-thread
  const [expired, setExpired] = useState([]);        // proposal ids that were replaced
  let MOD_SEQ = useRef(0);
  const [hasCard, setHasCard] = useState(() => localStorage.getItem("yoshi_card") === "1");
  const getCard = () => { localStorage.setItem("yoshi_card", "1"); setHasCard(true); };
  const rootRef = useRef(null);

  // theme → set on the .screen element so vars cascade to everything inside
  useEffect(() => {
    const el = document.getElementById("root");
    el.setAttribute("data-palette", palette);
  }, [palette]);
  const setPalette = (p) => { setPaletteState(p); localStorage.setItem("yoshi_palette", p); };

  const flash = (msg) => { setToast(msg); setTimeout(() => setToast(t => t === msg ? null : t), 2600); };

  const nav = useMemo(() => ({
    tab: (t) => { setStack([]); setOverlay(null); setTab(t); },
    studio: (view) => { setStack([]); setOverlay(null); setStudioView(view || "investments"); setTab("studio"); },
    push: (v) => setStack(s => [...s, v]),
    pop: () => setStack(s => s.slice(0, -1)),
    sheet: (o) => setOverlay(o),
    closeSheet: () => setOverlay(null),
    ask: (note, reply) => { setChatInject({ note, reply }); setStack([]); setOverlay(null); setTab("chat"); },
    automation: (id) => { setStack([]); setOverlay({ type: "automation", id }); },
    signOut: () => { localStorage.removeItem("yoshi_onboarded"); localStorage.removeItem("yoshi_card"); setHasCard(false); setOnboarded(false); setTab("home"); setStack([]); setOverlay(null); setProposals(PROPOSALS); setCompleted(COMPLETED); },
  }), []);

  const openApproval = (id) => setOverlay({ type: "approve", id });

  // ---- proposal threads -----------------------------------------------------
  const findProp = (id) => proposals.find((x) => x.id === id) || extraProposals.find((x) => x.id === id) || PROPOSALS.find((x) => x.id === id);
  const rootOf = (id) => { let p = findProp(id), guard = 0; while (p && p.modifiedFrom && guard++ < 12) p = findProp(p.modifiedFrom); return p ? p.id : id; };
  const tidFor = (id) => "th_" + rootOf(id);
  const isExpired = (id) => expired.includes(id);
  const hasThread = (id) => !!threads[tidFor(id)];

  // mint a revised (smaller) proposal from an existing one
  const scaleStr = (s, f) => String(s).replace(/\d[\d,]*(\.\d+)?/g, (mm) => {
    const n = parseFloat(mm.replace(/,/g, "")) * f;
    if (n >= 1000) return Math.round(n).toLocaleString();
    if (n >= 1) return (Math.round(n * 100) / 100).toLocaleString();
    return String(Math.round(n * 1000) / 1000);
  });
  const makeRevised = (p) => {
    MOD_SEQ.current += 1;
    const f = 0.5;
    return {
      ...p,
      id: p.id + "_m" + MOD_SEQ.current,
      modifiedFrom: p.id,
      net: Math.round(p.net * f * 100) / 100,
      why: "Revised down per your note: about half the original size, same direction. Smaller market impact, and it still moves you toward your target.",
      legs: p.legs.map((l) => l.map((cell, i) => i >= 2 ? scaleStr(cell, f) : cell))
    };
  };

  // create (or continue) the thread for a proposal, optionally seeding a question
  const openThread = (pid, userMsg) => {
    const tid = tidFor(pid);
    setThreads((ts) => {
      const existing = ts[tid];
      let msgs = existing ? existing.msgs : [{ kind: "proposal", id: rootOf(pid) }];
      if (userMsg) msgs = [...msgs, { from: "user", t: userMsg, time: "now" }, { from: "agent", t: window.threadReply(userMsg).t, time: "now" }];
      return { ...ts, [tid]: { id: tid, msgs } };
    });
    setOverlay({ type: "thread", tid });
  };
  const persistThread = (tid, msgs) => setThreads((ts) => ({ ...ts, [tid]: { ...(ts[tid] || { id: tid }), msgs } }));

  // Yoshi revises a proposal inside its thread: expire the old, mint + surface the new
  const reviseInThread = (origId) => {
    const p = findProp(origId);
    const pm = makeRevised(p);
    setExtraProposals((xs) => [...xs, pm]);
    setProposals((ps) => ps.some((x) => x.id === origId) ? ps.map((x) => x.id === origId ? pm : x) : [...ps, pm]);
    setExpired((e) => e.includes(origId) ? e : [...e, origId]);
    flash("Proposal revised");
    return pm.id;
  };

  const finishOnboarding = () => { localStorage.setItem("yoshi_onboarded", "1"); setOnboarded(true); };

  // approval outcomes
  const onApproved = (id) => {
    const p = proposals.find(x => x.id === id);
    const rest = proposals.filter(x => x.id !== id);
    setProposals(rest);
    setCompleted(cs => [{ id: "ex_" + id, title: p.title, detail: p.legs.map(l => l[1]).join(" · "), when: "May 29", net: p.net, by: p.agent }, ...cs]);
    if (rest[0]) setOverlay({ type: "approve", id: rest[0].id }); else setOverlay(null);
    flash("Executed · " + p.title);
  };
  const onDeclined = (id, reason) => {
    const p = proposals.find(x => x.id === id);
    const rest = proposals.filter(x => x.id !== id);
    setProposals(rest);
    if (rest[0]) setOverlay({ type: "approve", id: rest[0].id }); else setOverlay(null);
    flash("Declined · " + reason);
  };
  const onModified = (id, note) => {
    const p = proposals.find(x => x.id === id);
    setOverlay(null);
    setChatInject({ note, reply: `Got it — on "${p.title}": "${note}". Let me take a look and come back with an updated proposal you can approve.` });
    nav.tab("chat");
    flash("Sent back to Yoshi");
  };

  if (!onboarded) {
    return (
      <ThemeCtx.Provider value={palette}>
        <StatusBar />
        <Onboarding onDone={finishOnboarding} />
      </ThemeCtx.Provider>
    );
  }

  const screen = {
    home: <Home nav={nav} proposals={proposals} completed={completed} onApprove={openApproval} />,
    trade: <TradeSheet embedded nav={nav} onClose={() => nav.tab("home")} />,
    chat: <Chat nav={nav} proposals={proposals} onApprove={openApproval} inject={chatInject} onInjected={() => setChatInject(null)} />,
    accounts: <Accounts nav={nav} hasCard={hasCard} />,
    studio: <Studio nav={nav} initialView={studioView} proposals={proposals} onApprove={openApproval} />,
    profile: <Profile palette={palette} setPalette={setPalette} nav={nav} />,
  }[tab];

  return (
    <ThemeCtx.Provider value={palette}>
      <StatusBar />
      <div className="viewport" ref={rootRef}>
        <div key={tab} className="tab-swap" style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column" }}>
          {screen}
        </div>

        {/* push stack (holding detail) */}
        {stack.map((v, i) => (
          <div key={i} className="push-enter" style={{ position: "absolute", inset: 0, background: "var(--bg)", display: "flex", flexDirection: "column", zIndex: 100 + i }}>
            {v.type === "holding" && <HoldingDetail id={v.id} nav={nav} />}
            {v.type === "account" && <AccountDetail acct={v.acct} nav={nav} />}
            {v.type === "card" && <CardDetail nav={nav} flash={flash} hasCard={hasCard} onGetCard={getCard} />}
          </div>
        ))}

        {toast && <Toast msg={toast} />}
      </div>

      {tab !== "profile" && tab !== "chat" && <TabBar tab={tab} onTab={nav.tab} onTrade={() => nav.sheet({ type: "trade" })} />}

      {/* overlays */}
      {overlay?.type === "transfer" && <TransferFlow preset={overlay.from} intent={overlay.intent} initialRail={overlay.rail} onClose={nav.closeSheet} nav={nav} flash={flash} />}
      {overlay?.type === "txn" && <TxnDetailSheet tx={overlay.tx} onClose={nav.closeSheet} nav={nav} />}
      {overlay?.type === "trade" && <TradeSheet id={overlay.id} side={overlay.side} onClose={nav.closeSheet} nav={nav} />}
      {overlay?.type === "link" && <LinkSheet onClose={nav.closeSheet} />}
      {overlay?.type === "connect" && <ConnectAgentsSheet onClose={nav.closeSheet} nav={nav} />}
      {overlay?.type === "support" && <SupportFlow onClose={nav.closeSheet} nav={nav} />}
      {overlay?.type === "documents" && <DocumentsHub onClose={nav.closeSheet} nav={nav} flash={flash} initialAcct={overlay.acct} />}
      {overlay?.type === "briefs" && <BriefsHub onClose={nav.closeSheet} nav={nav} proposals={proposals} onApprove={openApproval} initialBriefId={overlay.brief} initialBrief={overlay.briefData} />}
      {overlay?.type === "automation" && (
        <AutomationSheet automation={AUTOMATIONS.find(a => a.id === overlay.id)} onClose={nav.closeSheet} nav={nav} flash={flash} />
      )}
      {overlay?.type === "approve" && (
        <ApprovalSheet key={overlay.id} proposal={findProp(overlay.id)}
          onClose={nav.closeSheet} onApproved={onApproved} onDeclined={onDeclined} onModified={onModified}
          onOpenThread={openThread} hasThread={hasThread(overlay.id)} />
      )}
      {overlay?.type === "thread" && (
        <ProposalThread key={overlay.tid} tid={overlay.tid} thread={threads[overlay.tid]}
          findProp={findProp} isExpired={isExpired} onReview={openApproval} onModify={reviseInThread}
          onPersist={persistThread} onClose={nav.closeSheet} />
      )}
    </ThemeCtx.Provider>
  );
};

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