// app.jsx — orchestrator: mode toggle (website/agent), view routing between
// the main pyramid, tier modals, stream funnels, the DNA assessment, the
// sub-pyramids, and the lens overlay.

const { useState, useEffect } = React;

function L180App() {
  const [mode, setMode] = useState("website");        // website | agent
  const [view, setView] = useState({ type: "main" }); // main | funnel | dna | subpyramid | lens
  const [modalTier, setModalTier] = useState(null);   // tier number or null

  const tiers = window.L180_TIERS;
  const orderTop = tiers;                              // top->bottom
  const tierByN = (n) => tiers.find((t) => t.n === n);

  // lock background scroll while an overlay view is active
  useEffect(() => {
    const overlay = view.type !== "main";
    document.body.style.overflow = overlay ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [view]);

  function openTier(n) { setModalTier(n); }
  function closeModal() { setModalTier(null); }

  // tier prev/next within the modal (by visual stack: down = lower tier)
  const modalIdx = modalTier ? tiers.findIndex((t) => t.n === modalTier) : -1;
  const lowerTier = modalIdx >= 0 && modalIdx < tiers.length - 1 ? tiers[modalIdx + 1].n : null;
  const higherTier = modalIdx > 0 ? tiers[modalIdx - 1].n : null;

  function onStream(tier, stream) {
    closeModal();
    if (stream.funnelType === "dna" || stream.isGateway) { setView({ type: "dna" }); return; }
    const fkey = window.l180FunnelKeyFor(tier.n, stream.name);
    if (fkey) setView({ type: "engine", tierN: tier.n, stream, fkey });
    else setView({ type: "funnel", tierN: tier.n, stream });
  }

  // continue-the-process: jump to the next stream in the same tier
  function continueNext(tierN, stream) {
    const t = tierByN(tierN);
    const idx = t.streams.findIndex((s) => s.name === stream.name);
    const nxt = t.streams[(idx + 1) % t.streams.length];
    onStream(t, nxt);
  }

  function onRoute(result) {
    if (result.route === "analyst" || result.route === "strategist") {
      setView({ type: "subpyramid", key: result.route, result });
    } else {
      setView({ type: "lens", result });
    }
  }

  return (
    <div>
      {/* top bar */}
      <div className="l180-topbar">
        <div className="l180-brandmark">
          <img className="l180-logo" src="https://assets.cdn.filesafe.space/YxdIpZn0CCUlZu8wTtjt/media/67d48eab1c7cb784002b20ed.png" alt="LIFE180" />
          <span className="tag">{mode === "agent" ? "Agent · Conversation Map" : "The Process"}</span>
        </div>
        <div className="l180-modetoggle" title="Website shows the public teaser. Agent reveals the deeper layer.">
          <button className={mode === "website" ? "on" : ""} onClick={() => setMode("website")}>Website</button>
          <button className={mode === "agent" ? "on" : ""} onClick={() => setMode("agent")}>Agent</button>
        </div>
      </div>

      {/* main pyramid (always mounted so scroll position persists) */}
      <L180Pyramid mode={mode} onOpenTier={openTier} />

      {/* tier modal */}
      {modalTier && (
        <L180TierModal
          tier={tierByN(modalTier)}
          mode={mode}
          onClose={closeModal}
          onPrev={lowerTier ? () => setModalTier(lowerTier) : null}
          onNext={higherTier ? () => setModalTier(higherTier) : null}
          onStream={onStream}
        />
      )}

      {/* funnel (generic stub) */}
      {view.type === "funnel" && (
        <L180Funnel
          tier={tierByN(view.tierN)}
          stream={view.stream}
          mode={mode}
          onExit={() => setView({ type: "main" })}
        />
      )}

      {/* funnel (config-driven engine) */}
      {view.type === "engine" && (
        <L180FunnelEngine
          cfg={window.L180_FUNNELS[view.fkey]}
          tier={tierByN(view.tierN)}
          mode={mode}
          onExit={() => setView({ type: "main" })}
          onContinueNext={() => continueNext(view.tierN, view.stream)}
        />
      )}

      {/* DNA assessment */}
      {view.type === "dna" && (
        <L180DNA
          mode={mode}
          onExit={() => setView({ type: "main" })}
          onRoute={onRoute}
        />
      )}

      {/* sub-pyramid */}
      {view.type === "subpyramid" && (
        <L180SubPyramid
          data={window.L180_SUBPYRAMIDS[view.key]}
          result={view.result}
          mode={mode}
          onExit={() => setView({ type: "main" })}
        />
      )}

      {/* lens overlay */}
      {view.type === "lens" && (
        <L180Lens
          result={view.result}
          onExit={() => setView({ type: "main" })}
          onReturn={() => setView({ type: "main" })}
        />
      )}
    </div>
  );
}

// Error boundary: a one-off cold-load race self-heals by retrying instead of
// showing a permanent black screen.
class L180Boundary extends React.Component {
  constructor(p) { super(p); this.state = { err: false, tries: 0 }; }
  static getDerivedStateFromError() { return { err: true }; }
  componentDidCatch() {
    if (this.state.tries < 5) setTimeout(() => this.setState((s) => ({ err: false, tries: s.tries + 1 })), 60);
  }
  render() {
    if (this.state.err) return null;
    return this.props.children;
  }
}

// Mount only once every dependency global is present (guards the babel
// external-script execution race).
function l180Ready() {
  return window.L180_TIERS && window.L180_SUBPYRAMIDS && window.L180_FUNNELS &&
    window.L180Pyramid && window.L180TierModal && window.L180Funnel &&
    window.L180FunnelEngine && window.L180DNA && window.L180SubPyramid &&
    window.L180Lens && window.l180TierHue && window.l180ScoreDNA;
}
function l180Mount() {
  if (!l180Ready()) { setTimeout(l180Mount, 30); return; }
  ReactDOM.createRoot(document.getElementById("root")).render(
    <L180Boundary><L180App /></L180Boundary>
  );
}
l180Mount();
