// App Router + Mount
const { useState: appSt, useEffect: appEf } = React;
const AppCtx = window.AppCtx;

function App() {
  const stored     = Store.session;
  const [session,   setSession]   = appSt(stored?.loggedIn ? stored : null);
  const [page,      setPage]      = appSt('dashboard');
  const [companyId, setCompanyId] = appSt(Store.currentCompanyId);
  // navParams — lightweight deep-link payload for cross-module traceability
  // (e.g. Diesel Split Allocation → jump straight to a specific Vendor/Transport
  // Settlement row, or the reverse). Consumed once by the destination page's
  // own effect, then the page is responsible for clearing what it used.
  const [navParams, setNavParams] = appSt(null);

  // ── Login loading screen (post-login animation) ────────────────────────
  // pendingUser holds the authenticated user until onReveal fires —
  // session is NOT set until then, so the dashboard never mounts early.
  const [showLoading, setShowLoading] = appSt(false);
  const [pendingUser, setPendingUser] = appSt(null);

  // ── Logout animation overlay ───────────────────────────────────────────
  // 'animating' → overlay visible, ERP still rendered underneath
  // 'revealing'  → session cleared, login mounted, overlay fading out
  const [logoutPhase, setLogoutPhase] = appSt(null);

  // ── Cinematic cold-start intro (v13+) ──────────────────────────────────
  // Signals window._omIntro (injected before React by the inline script in
  // OM Group ERP v13.html) that React has completed its first render and the
  // app is ready for the crossfade reveal.  Gracefully no-ops on older
  // HTML versions that do not include the intro script.
  appEf(function () {
    // Signal whichever splash/loader is active.
    // v25 and earlier use window._omIntro.onAppReady();
    // Test Ready uses window.__omSignalAppReady().
    // Both are called so either loader works without app.jsx changes.
    if (window._omIntro && window._omIntro.onAppReady) window._omIntro.onAppReady();
    if (window.__omSignalAppReady) window.__omSignalAppReady();
  }, []); // empty deps — fires exactly once after first render

  function setCompany(id) {
    Store.setCompany(id);
    setCompanyId(id);
  }

  function navigate(p, params) { setPage(p); setNavParams(params || null); }

  // ── Login flow ─────────────────────────────────────────────────────────
  function handleLogin(user) {
    setPendingUser(user);
    setShowLoading(true);
  }

  // Called by AppLoadingScreen at t=3.6 s — overlay still opaque,
  // safe to mount the dashboard behind it.
  function handleReveal() {
    if (pendingUser) {
      setSession({ loggedIn: true, userId: pendingUser.id,
                   userName: pendingUser.name, userEmail: pendingUser.email,
                   userRole: pendingUser.role });
      setCompanyId(Store.currentCompanyId);
      setPage('dashboard');
    }
  }

  function handleLoadingComplete() {
    setShowLoading(false);
    setPendingUser(null);
  }

  // ── Logout flow ────────────────────────────────────────────────────────
  // Step 1: user clicks Sign Out → mount overlay immediately (same render)
  function handleLogout() {
    setLogoutPhase('animating');
  }

  // Step 2: overlay calls this at t≈4.0 s (white-out begins in animation)
  // Clear session now — login page mounts silently behind the overlay.
  function handleLogoutReveal() {
    Store.logout();
    setSession(null);
    setPage('dashboard');
    setCompanyId(Store.currentCompanyId);
    setLogoutPhase('revealing');
  }

  // Step 3: overlay fully dissolved (~t=5.5 s) → unmount it
  function handleLogoutDone() {
    setLogoutPhase(null);
  }

  const ctx = { page, navigate, companyId, setCompany, session, navParams, clearNavParams: function(){ setNavParams(null); } };

  // ── Page map ────────────────────────────────────────────────────────────
  const isGroup = companyId === 'group';
  const pages = {
    dashboard:           isGroup ? <window.GroupDashboardPage /> : <window.DashboardPage />,
    calendar:            <window.GroupCalendarPage />,
    analytics:           window.IntelCenterPage ? <window.IntelCenterPage /> : <window.DashboardPage />,
    reports:             <window.ReportsPage />,
    materials:           <window.MaterialsPage />,
    customers:           <window.CustomersPage />,
    vendors:             <window.VendorsPage />,
    crusher:             <window.CrusherPage />,
    sales:               <window.SalesPage />,
    purchases:           <window.PurchasesPage />,
    vendorsettlement:    <window.VendorSettlementPage />,
    transfers:           <window.InternalTransfersPage />,
    debris:              <window.DebrisMovementPage />,
    stockyard:           <window.StockyardPage />,
    rmcplants:           <window.RMCPlantsPage />,
    transportermaster:   <window.TransporterMasterPage />,
    transport:           <window.TransportPage />,
    transportsettlement: <window.TransportSettlementPage />,
    settlementpolicy:    <window.SettlementPolicyPage />,
    transporters:        <window.TransportersListPage />,
    priceorders:         <window.PriceOrdersPage />,
    rates:               <window.RatesPage />,
    diesel:              <window.DieselPage />,
    companies:           <window.CompaniesPage />,
    users:               <window.UsersPage />,
    audit:               <window.AuditPage />,
    datahealth:          window.DataHealthPage ? <window.DataHealthPage /> : null,
  };

  return (
    <AppCtx.Provider value={ctx}>

      {/* ── Login page ────────────────────────────────────────────────────
           Rendered whenever there is no active session.
           During logout, this mounts silently behind the overlay at t≈4 s,
           then becomes visible as the overlay dissolves away.
           The `om-logout-login-reveal` class starts the gentle settle-in
           animation only when revealed via the logout flow. */}
      {!session?.loggedIn && (
        <div className={logoutPhase === 'revealing' ? 'om-logout-login-reveal' : ''}>
          <window.LoginPage onLogin={handleLogin} />
        </div>
      )}

      {/* ── ERP application shell ─────────────────────────────────────── */}
      {session?.loggedIn && (
        <window.AppLayout page={page} navigate={navigate}
                          session={session} onLogout={handleLogout}>
          {/* key={page} remounts page content on navigation */}
          <div key={page} className="erp-page-enter">
            {pages[page] || <window.DashboardPage />}
          </div>
        </window.AppLayout>
      )}

      {/* ── Branded login loading overlay ─────────────────────────────────
           Covers the login page on sign-in; session is set inside onReveal
           so the dashboard renders behind the still-opaque overlay and is
           fully ready when it fades to transparent. */}
      {showLoading && (
        <window.AppLoadingScreen
          onReveal={handleReveal}
          onComplete={handleLoadingComplete}
        />
      )}

      {/* ── Logout animation overlay ──────────────────────────────────────
           Rendered at the TOP LEVEL — z-index 9998, covers everything.
           Mounts the instant Sign Out is clicked; unmounts only after the
           animation fully dissolves (~5.5 s total). */}
      {logoutPhase && (
        <window.LogoutOverlay
          onReadyToShowLogin={handleLogoutReveal}
          onComplete={handleLogoutDone}
        />
      )}

      {/* ── OM ERP AI Agent ───────────────────────────────────────────────
           Additive intelligence layer. Guarded so any ERP build that does not
           load the agent scripts is completely unaffected, and so an agent
           failure can never take the ERP down with it. */}
      {session?.loggedIn && !logoutPhase && window.ERPAgent && (
        <window.ErrorBoundary fallback={() => null}>
          <window.ERPAgent />
        </window.ErrorBoundary>
      )}

      <window.ToastHost />
    </AppCtx.Provider>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
// Mounts immediately — Store's constructor already populated Store.data
// synchronously (from the small legacy localStorage snapshot, or fresh seed).
// The large-capacity IndexedDB upgrade keeps loading in the background and
// swaps in the full dataset when ready, same as any other store mutation —
// every module already re-renders on Store.on(), so nothing extra is needed
// here and first paint is never blocked on it.
root.render(
  <window.ErrorBoundary fallback={() => (
    <div style={{minHeight:'100vh',display:'flex',alignItems:'center',justifyContent:'center',flexDirection:'column',gap:14,fontFamily:'var(--font, sans-serif)',padding:20,textAlign:'center'}}>
      <div style={{fontSize:18,fontWeight:700}}>Something went wrong.</div>
      <div style={{fontSize:13,color:'#666',maxWidth:420}}>An unexpected error occurred while rendering the app. Your data is safe — reloading will restore the page.</div>
      <button className="btn btn-or" onClick={()=>location.reload()}>Reload</button>
    </div>
  )}>
    <App />
  </window.ErrorBoundary>
);
