// ────────────────────────────────────────────────────────────────────────────
// app-shell.jsx — Unified app shell · router + screen switcher
// Foundation v1 · v1.7.0 · index.html runtime
//
// Responsibilities:
//   1. Subscribe to hash route (useHashRoute from app-data.jsx)
//   2. Pick screen component based on route + viewport
//   3. Wire navigation:
//        · Event delegation on [data-tab-key] and [data-app-nav]
//        · Profile menu (onMenuTap) → navTo
//        · PfPageBar back buttons → navTo (via onBack prop)
//   4. Render canonical chrome (DesktopTopbar / BottomNav) ONLY when the
//      screen doesn't already include it.
//   5. Manage shared state that lives across the shell:
//        · locale (FA default; switchable via window.__APP_LOCALE setter)
//        · logoutOpen for Profile routes
//
// Mounts onto #app-root (NOT #root). Individual artifact pages (Profile.html,
// Shop.html, etc.) still mount their own DesignCanvas to #root and remain
// unaffected because the shell sets `window.__APP_SHELL_MODE = true` before
// loading -app.jsx files.
// ────────────────────────────────────────────────────────────────────────────

// ─── Helpers ────────────────────────────────────────────────────────────────
// Routes whose mobile screen already includes its own <BottomNav>.
// The shell skips adding an external one for these so we don't double-stack.
const APP_BOTTOMNAV_BUILTIN = new Set(['home', 'predict', 'shop', 'leaderboard']);

// Routes that are part of the BottomNav (primary navigation).
// For these, mobile gets a BottomNav (either built-in or shell-added).
const APP_PRIMARY_TABS = new Set(['home', 'predict', 'lineup', 'cards', 'leaderboard', 'shop']);

// Routes whose desktop screen already includes its own top chrome
// (canonical DesktopTopbar or a bespoke equivalent like Lineup's lu-desk-topbar).
const APP_DESKTOP_TOPBAR_BUILTIN = new Set([
  'home', 'predict', 'shop', 'leaderboard', 'profile', 'lineup',
]);

// Routes that, on desktop, should NOT show ANY top chrome (deep secondary pages).
const APP_DESKTOP_NO_CHROME = new Set([
  'profileEdit',
]);


// ─── Lineup props builder ───────────────────────────────────────────────────
// Lineup variants need a fully derived prop bundle. We assemble it here once
// per render and pass it to LineupSwitcher / DesktopMockup.
function useLineupProps(locale, state = 'complete') {
  return React.useMemo(() => {
    const bundle = window.deriveStateBundle ? window.deriveStateBundle(state) : null;
    if (!bundle) return null;
    const score = window.computeDeckScore
      ? window.computeDeckScore(bundle.slots, bundle.fanCard?.bonus || 0, bundle.coachCard?.multiplier || 1.0)
      : 0;
    return {
      locale,
      slots: bundle.slots,
      fanCard: bundle.fanCard,
      coachCard: bundle.coachCard,
      score,
      submitState: bundle.submitState,
      showBreakdown: true,
      showSpecial: true,
      deadline: '02:14:36',
      invalidIds: bundle.invalidIds,
      onPick: () => {}, onPickFan: () => {}, onPickCoach: () => {},
      onRemoveSlot: () => {}, onRemoveFan: () => {}, onRemoveCoach: () => {},
    };
  }, [locale, state]);
}


// ─── ScreenSwitcher — picks the right screen by route + viewport ────────────
function ScreenSwitcher({ route, locale, isDesktop, logoutOpen, setLogoutOpen }) {
  const navHome = () => window.navTo('home');
  const navProfile = () => window.navTo('profile');

  const onProfileMenuTap = (item) => {
    if (item.key === 'logout') { setLogoutOpen(true); return; }
    const target = window.APP_MENU_TO_ROUTE[item.key];
    if (target) window.navTo(target);
  };

  const lineupProps = useLineupProps(locale, 'complete');

  switch (route) {
    // ── Home Hub ─────────────────────────────────────────────────────────────
    case 'home': {
      if (isDesktop) {
        return <window.DesktopBento locale={locale} dateMode="hybrid"/>;
      }
      return <window.MobileBento locale={locale}
                                 avatarSide="start"
                                 fiveTabs={false}
                                 scrollAware={true}
                                 dateMode="hybrid"
                                 notifSimulate={true}/>;
    }

    // ── Prediction Hub ───────────────────────────────────────────────────────
    case 'predict': {
      if (isDesktop) return <window.DesktopLayout locale={locale} dateMode="hybrid"/>;
      return <window.MobileExpC locale={locale} dateMode="hybrid"/>;
    }

    // ── Lineup Builder ──────────────────────────────────────────────────────
    case 'lineup': {
      if (!lineupProps) return null;
      if (isDesktop) {
        return (
          <window.DesktopMockup locale={locale}
                                variantKey="landscape"
                                renderVariant={(k) =>
                                  k === 'landscape'
                                    ? <window.VariantLandscape {...lineupProps}/>
                                    : <window.VariantTactical {...lineupProps}/>
                                }
                                score={lineupProps.score}
                                variantProps={lineupProps}/>
        );
      }
      return <window.LineupSwitcher initialOrientation="vertical" {...lineupProps}/>;
    }

    // ── My Cards ────────────────────────────────────────────────────────────
    case 'cards': {
      return <window.InventoryScreen locale={locale} desktop={isDesktop} density={2}/>;
    }

    // ── Leaderboard ─────────────────────────────────────────────────────────
    case 'leaderboard': {
      if (isDesktop) return <window.LeaderboardDesktop locale={locale}/>;
      return <window.LeaderboardMobile locale={locale}/>;
    }

    // ── Shop ────────────────────────────────────────────────────────────────
    case 'shop': {
      if (isDesktop) return <window.ShopDesktop locale={locale} defaultFilter="all"/>;
      return <window.ShopMobile locale={locale} dateMode="hybrid"/>;
    }

    // ── Profile ─────────────────────────────────────────────────────────────
    case 'profile': {
      const Component = isDesktop ? window.ProfileDesktop : window.ProfileMobile;
      return (
        <Component locale={locale}
                   onBack={navHome}
                   onEdit={() => window.navTo('profileEdit')}
                   onMenuTap={onProfileMenuTap}
                   logoutOpen={logoutOpen}
                   onLogoutClose={(action) => {
                     if (action === 'open') setLogoutOpen(true);
                     else                   setLogoutOpen(false);
                   }}/>
      );
    }
    case 'profileEdit': {
      return <window.EditProfileScreen locale={locale} onBack={navProfile}/>;
    }

    // ── Placeholder routes (Coming Soon) ────────────────────────────────────
    case 'settings':
    case 'notifications':
    case 'about':
    case 'lineupHistory':
    case 'packOpening':
      return <window.ComingSoonScreen route={route} locale={locale}/>;

    // ── Fallback ────────────────────────────────────────────────────────────
    default:
      return <window.NotFoundScreen locale={locale}/>;
  }
}


// ─── AppShell — root component for the unified SPA ──────────────────────────
function AppShell() {
  const route       = window.useHashRoute('home');
  const { isDesktop } = window.useViewport(1024);
  const [locale, setLocale] = React.useState(window.__APP_LOCALE || 'fa');
  const [logoutOpen, setLogoutOpen] = React.useState(false);

  // Expose locale setter for the optional language switcher in the demo bar.
  React.useEffect(() => {
    window.__APP_SET_LOCALE = (loc) => {
      if (['fa', 'en', 'ar'].indexOf(loc) >= 0) setLocale(loc);
    };
    return () => { delete window.__APP_SET_LOCALE; };
  }, []);

  // Apply lang/dir on every locale change. RTL-first default (fa).
  React.useEffect(() => {
    document.documentElement.lang = locale;
    document.documentElement.dir  = locale === 'en' ? 'ltr' : 'rtl';
    window.__APP_LOCALE = locale;
  }, [locale]);

  // ─── Event delegation for navigation ──────────────────────────────────────
  // Catches clicks on [data-tab-key] (BottomNav, DesktopTopbar nav) and
  // [data-app-nav] (avatar, bell). One listener at the document level — no
  // per-component wiring needed. Existing onClick handlers on these buttons
  // remain a no-op for navigation purposes (they were demo-only callbacks).
  React.useEffect(() => {
    const onClick = (e) => {
      const tab = e.target.closest('[data-tab-key]');
      if (tab) {
        const key = tab.dataset.tabKey;
        const target = window.APP_TAB_TO_ROUTE[key];
        if (target) {
          e.preventDefault();
          window.navTo(target);
        }
        return;
      }
      const nav = e.target.closest('[data-app-nav]');
      if (nav) {
        e.preventDefault();
        window.navTo(nav.dataset.appNav);
        return;
      }
    };
    document.addEventListener('click', onClick);
    return () => document.removeEventListener('click', onClick);
  }, []);

  // ─── Layout decision ──────────────────────────────────────────────────────
  // Mobile: routes outside the primary tabs (e.g. /profile, /settings) don't
  // get a BottomNav. Lineup + Cards do (shell adds one externally).
  const needsExternalBottomNav =
    !isDesktop &&
    APP_PRIMARY_TABS.has(route) &&
    !APP_BOTTOMNAV_BUILTIN.has(route);

  // Desktop secondary pages (settings, edit, notifications) get a small
  // canonical chrome above the content so user always has nav context.
  const needsExternalDesktopTopbar =
    isDesktop &&
    !APP_DESKTOP_TOPBAR_BUILTIN.has(route) &&
    !APP_DESKTOP_NO_CHROME.has(route);

  const activeTabKey = window.APP_ROUTES[route]?.tabKey || 'home';

  return (
    <div className={`app-shell-root ${isDesktop ? 'is-desktop' : 'is-mobile'}`}>
      {needsExternalDesktopTopbar && window.DesktopTopbar && (
        <window.DesktopTopbar locale={locale}
                              user={window.adaptUserForTopbar(window.HH_USER, locale)}
                              activeTab={activeTabKey}
                              notifications={3}/>
      )}

      <div className="app-shell-viewport">
        <ScreenSwitcher route={route}
                        locale={locale}
                        isDesktop={isDesktop}
                        logoutOpen={logoutOpen}
                        setLogoutOpen={setLogoutOpen}/>
      </div>

      {needsExternalBottomNav && window.BottomNav && (
        <window.BottomNav locale={locale}
                          activeTab={activeTabKey}
                          shrunk={false}
                          scrollAware={false}
                          fiveTabs={false}/>
      )}
    </div>
  );
}


// ─── Local styles ───────────────────────────────────────────────────────────
// Only layout chrome; no new design tokens.
const APP_SHELL_CSS = `
  html, body, #app-root { margin: 0; padding: 0; }
  html, body { background: var(--bg-deep); color: var(--text-primary); }
  body, button, input, textarea, select {
    font-family: var(--font-fa), system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
  }

  #app-root {
    inline-size: 100%;
    min-block-size: 100vh;
  }

  .app-shell-root {
    position: relative;
    inline-size: 100%;
    min-block-size: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bg-deep);
  }

  .app-shell-viewport {
    flex: 1;
    inline-size: 100%;
    min-block-size: 100vh;
    overflow-x: hidden;
  }

  /* When the shell adds an external BottomNav, leave room below content
     so nothing is occluded by the fixed nav. Native BottomNav height ~64px. */
  .app-shell-root.is-mobile:has(> .hh-bnav) .app-shell-viewport {
    padding-block-end: 72px;
  }
  /* Fallback for browsers without :has() — also pad when class is set. */
  .app-shell-root.is-mobile .app-shell-viewport.has-ext-bnav {
    padding-block-end: 72px;
  }

  /* Mobile shell — center the viewport content (each screen already
     has its own scroll container, so we don't add another one here). */
  .app-shell-root.is-mobile .app-shell-viewport > * {
    inline-size: 100%;
    min-block-size: 100vh;
  }

  /* Desktop — full width, no max constraint (screens handle their own widths). */
  .app-shell-root.is-desktop .app-shell-viewport {
    min-block-size: calc(100vh - 0px);
  }

  /* Smooth view transitions (opacity + transform only) */
  .app-shell-viewport > * {
    animation: app-fade-in 220ms ease-out;
  }
  @keyframes app-fade-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
  }
  @media (prefers-reduced-motion: reduce) {
    .app-shell-viewport > * { animation: none; }
  }
`;

if (typeof document !== 'undefined' &&
    !document.getElementById('app-shell-css')) {
  const s = document.createElement('style');
  s.id = 'app-shell-css';
  s.textContent = APP_SHELL_CSS;
  document.head.appendChild(s);
}


// ─── Mount ──────────────────────────────────────────────────────────────────
// Only mounts when the host page has an #app-root and we're in shell mode
// (set by index.html before any -app.jsx loads).
const __appShellRoot = typeof document !== 'undefined'
  ? document.getElementById('app-root')
  : null;

if (__appShellRoot && window.__APP_SHELL_MODE) {
  ReactDOM.createRoot(__appShellRoot).render(<AppShell/>);
}

Object.assign(window, { AppShell, ScreenSwitcher });
