/**
 * App — BrowserRouter shell with react-router declarative routing.
 *
 * Routes:
 *   /             → redirect to /calendar
 *   /calendar     → CalendarShell
 *   /lists        → ListsIndex
 *   /lists/:listId → ListDetail (placeholder for Plan 04-04)
 *
 * Layout:
 *   AppNav is rendered as a PERSISTENT sibling of <Routes> (outside any Route),
 *   so it survives route transitions (FIX 3). AppNav provides:
 *     - Phone (≤767px): 48px top bar (the header above the main content area)
 *     - Desktop (≥768px): 240px left sidebar with nav links + colour legend
 *
 *   BottomTabBar is also a sibling of <Routes> so the tab state remains consistent.
 *   On desktop (≥768px) BottomTabBar is hidden via CSS (FIX 4).
 *
 * Auth flow:
 *   /api/me is fetched once at the App level. While loading or on error the
 *   full-screen AuthSplash overlay is shown (CalendarShell's AuthSplash is
 *   positioned fixed with z-index so it covers AppNav too). AppNav renders
 *   with empty / partial data until auth resolves — this is fine because the
 *   AuthSplash overlay hides the AppNav during that window.
 *
 * navigateFallback ('/index.html') in vite.config.ts covers SPA deep-links to
 * /lists/* — the SW denylist only excludes /callback, /api/, and /health, so
 * /lists/* is served from cache correctly.
 *
 * Phase 5 additions:
 *   - PermissionDeniedBanner: shown below AppNav when OS permission revoked (D-10)
 *   - SettingsSheet: avatar-triggered bottom sheet with master notifications toggle (D-09)
 *
 * Phase 6 fix (FIX 3):
 *   - AppNav lifted from CalendarShell to this level so /lists keeps the nav chrome.
 *   - /api/me query shared so AppNav has user data on all routes.
 */

import { useState, useMemo } from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router';
import { useQuery } from '@tanstack/react-query';
import { CalendarShell } from './components/CalendarShell.js';
import { ListsIndex } from './routes/ListsIndex.js';
import { ListDetail } from './routes/ListDetail.js';
import { BottomTabBar } from './components/BottomTabBar.js';
import { AppNav } from './components/AppNav.js';
import { PushPermissionPrompt } from './components/PushPermissionPrompt.js';
import { PermissionDeniedBanner } from './components/PermissionDeniedBanner.js';
import { SettingsSheet } from './components/SettingsSheet.js';
import { fetchMe } from './api/client.js';

function isPhone(): boolean {
  return typeof window !== 'undefined' && window.matchMedia('(max-width: 767px)').matches;
}

export default function App() {
  const [settingsOpen, setSettingsOpen] = useState(false);
  const phone = isPhone();

  // Fetch current user once at the app shell level so AppNav has member data on
  // ALL routes. This is the same query key (['me']) used by CalendarShell, so
  // TanStack Query deduplicates the request — no double fetch.
  const meQuery = useQuery({
    queryKey: ['me'],
    queryFn: fetchMe,
    retry: false,
    staleTime: 5 * 60 * 1000,
  });

  // Derive members for AppNav from the shared /api/me response
  const members = useMemo(() => {
    if (!meQuery.data?.user) return [];
    return [
      {
        id: String(meQuery.data.user.id),
        name: meQuery.data.user.displayName ?? 'Member',
        color: meQuery.data.user.color,
      },
    ];
  }, [meQuery.data]);

  // Outer layout: phone = column, desktop = row (AppNav sidebar + content)
  const outerStyle: React.CSSProperties = {
    height: '100dvh',
    display: 'flex',
    flexDirection: phone ? 'column' : 'row',
    background: 'var(--color-surface)',
    color: 'var(--color-text-primary)',
    fontFamily: 'var(--font-family-base)',
    overflow: 'hidden',
  };

  // Content area: fills remaining space next to / below AppNav
  const contentStyle: React.CSSProperties = {
    flex: 1,
    minWidth: 0,
    minHeight: 0,
    display: 'flex',
    flexDirection: 'column',
    overflow: 'hidden',
    position: 'relative',
  };

  return (
    <BrowserRouter>
      {/* Permission-denied banner: shown when OS revoked and user had notifications on (D-10) */}
      <PermissionDeniedBanner />

      <div style={outerStyle}>
        {/* Persistent AppNav — phone: top bar; desktop: left sidebar.
            Renders on ALL routes so nav chrome survives route transitions (FIX 3). */}
        <AppNav
          members={members}
          currentUserColor={meQuery.data?.user.color}
          currentUserName={meQuery.data?.user.displayName ?? undefined}
          onOpenSettings={() => setSettingsOpen(true)}
        />

        {/* Main content area — all routes render here */}
        <div style={contentStyle}>
          <Routes>
            <Route path="/" element={<Navigate to="/calendar" replace />} />
            <Route path="/calendar" element={<CalendarShell />} />
            <Route path="/lists" element={<ListsIndex />} />
            <Route path="/lists/:listId" element={<ListDetail />} />
          </Routes>
        </div>
      </div>

      {/* BottomTabBar — phone-only (hidden ≥768px via CSS, FIX 4) */}
      <BottomTabBar />

      {/* Post-install permission prompt (D-08): renders only when isInstalled() is true
          and Notification.permission === 'default' and not dismissed */}
      <PushPermissionPrompt />

      {/* Settings sheet — master notifications toggle (D-09), opened from avatar */}
      <SettingsSheet isOpen={settingsOpen} onClose={() => setSettingsOpen(false)} />
    </BrowserRouter>
  );
}
