// Renames legacy persisted storage keys before the store is read (same as frontend/main.tsx).
import '@/lib/brandStorage';
import '@/lib/cookieAuthEnv';
import { StrictMode, Suspense, lazy, useEffect, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Navigate, Outlet, Route, Routes } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { Toaster } from 'react-hot-toast';
import { installApiFetchInterceptor } from '@wevsoft/shared/api/fetch-interceptor';
import { consumeAuthHandoff, stripAuthHandoffHash } from '@wevsoft/shared/api/auth-handoff';
import { allowHandoffBounce, buildHandoffLoginUrl, exchangeHandoffCode, resetHandoffBounces, takeHandoffCode } from '@wevsoft/shared/api/auth-handoff-code';
import { COOKIE_SESSION_MARKER, cookieOnlyClient } from '@wevsoft/shared/api/cookie-auth';
import '@/i18n';
import './index.css';
import { useStore } from '@/store';
import { apiUrl } from '@/lib/apiBase';
import { applyDisplayModeToDocument } from '@/lib/statusBarTheme';
import RouteFallback from '@/components/RouteFallback';
import BusinessLayout from './BusinessLayout';
import { SpaceProvider } from './SpaceContext';
import { mainAppLoginUrl } from './mainAppUrl';

const HomePage = lazy(() => import('./pages/HomePage'));
const InboxPage = lazy(() => import('./pages/InboxPage'));
const ContentPage = lazy(() => import('./pages/ContentPage'));
const LeadsPage = lazy(() => import('./pages/LeadsPage'));
const ShopPage = lazy(() => import('./pages/ShopPage'));
const AdsPage = lazy(() => import('./pages/AdsPage'));
const AutomationsPage = lazy(() => import('./pages/AutomationsPage'));
const SpacePanelPage = lazy(() => import('./pages/SpacePanelPage'));
const InsightsPage = lazy(() => import('./pages/InsightsPage'));
const WhatsAppPage = lazy(() => import('./pages/WhatsAppPage'));
const ContentLibraryPage = lazy(() => import('./pages/ContentLibraryPage'));
const NotificationsPage = lazy(() => import('./pages/NotificationsPage'));
const PublicLeadForm = lazy(() => import('./pages/PublicLeadForm'));
const PublicBooking = lazy(() => import('./pages/PublicBooking'));
const SupportPage = lazy(() => import('./pages/SupportPage'));
const CreatorsPage = lazy(() => import('./pages/CreatorsPage'));
const BrandSafetyPage = lazy(() => import('./pages/BrandSafetyPage'));
const LivePage = lazy(() => import('./pages/LivePage'));
const InspirationPage = lazy(() => import('./pages/InspirationPage'));

try {
  applyDisplayModeToDocument(localStorage.getItem('theme'));
} catch {
  applyDisplayModeToDocument('Light mode');
}

// WS7c: the legacy raw-token hash (`#wev_handoff`) is accepted only while cookie-only
// mode is off (deploy skew with an older main app); otherwise it is stripped unread.
if (cookieOnlyClient()) {
  stripAuthHandoffHash();
} else {
  const handoff = consumeAuthHandoff();
  if (handoff) useStore.getState().setAuth(handoff.token, handoff.user as never);
}

installApiFetchInterceptor({
  resolveBackendUrl: apiUrl,
  onUnauthorized: () => {
    const store = useStore.getState();
    if (store.token) store.logout();
  },
});

// WS7c: one-time handoff code (`#wev_code`, 60 s, bound to this origin) + PKCE verifier
// kept in sessionStorage. Runs after the interceptor so /api resolves to the backend.
const pendingHandoff = takeHandoffCode();
const handoffExchange: Promise<void> | null = pendingHandoff
  ? exchangeHandoffCode(pendingHandoff).then((session) => {
      if (!session?.user) return;
      useStore.getState().setAuth(session.token || COOKIE_SESSION_MARKER, session.user as never);
      resetHandoffBounces();
    })
  : null;

/** Waits for a pending handoff exchange, then bounces to main-app sign-in with a fresh challenge. */
function useHandoffGate(token: string | null): { waiting: boolean; blocked: boolean } {
  const [waiting, setWaiting] = useState(Boolean(handoffExchange));
  const [blocked, setBlocked] = useState(false);
  useEffect(() => {
    if (handoffExchange) void handoffExchange.finally(() => setWaiting(false));
  }, []);
  useEffect(() => {
    if (token || waiting) return;
    if (!allowHandoffBounce()) {
      setBlocked(true);
      return;
    }
    buildHandoffLoginUrl(mainAppLoginUrl, window.location.href)
      .catch(() => mainAppLoginUrl())
      .then((url) => window.location.replace(url));
  }, [token, waiting]);
  return { waiting, blocked };
}

function HandoffBlocked() {
  return (
    <div style={{ padding: 24, textAlign: 'center' }}>
      <p>Sign-in could not be completed.</p>
      <a href={mainAppLoginUrl()} onClick={() => resetHandoffBounces()}>Try again</a>
    </div>
  );
}

const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 30_000, retry: 1, refetchOnWindowFocus: false } } });

/** Not signed in → sign in on the main app, which hands the session back here. */
function RequireAuth() {
  const token = useStore((s) => s.token);
  const { blocked } = useHandoffGate(token);
  if (!token) return blocked ? <HandoffBlocked /> : <RouteFallback />;
  return <SpaceProvider><Outlet /></SpaceProvider>;
}

function App() {
  const { token, setAuth } = useStore();
  useEffect(() => {
    if (!token) return;
    fetch('/api/profile', { headers: { Authorization: `Bearer ${token}` } })
      .then((res) => (res.ok ? res.json() : null))
      .then((profile) => { if (profile) setAuth(token, { ...(useStore.getState().user || {}), ...profile }); })
      .catch(() => {});
  }, [token, setAuth]);

  return (
    <QueryClientProvider client={queryClient}>
      <Toaster position="top-center" toastOptions={{ className: 'dark:bg-zinc-900 dark:text-white' }} />
      <BrowserRouter>
        <Suspense fallback={<RouteFallback />}>
          <Routes>
            <Route path="/business/f/:formId" element={<PublicLeadForm />} />
            <Route path="/business/b/:ownerId" element={<PublicBooking />} />
            <Route element={<RequireAuth />}>
              <Route path="/business" element={<BusinessLayout />}>
                <Route index element={<HomePage />} />
                <Route path="dashboard" element={<Navigate to="/business" replace />} />
                <Route path="inbox" element={<InboxPage />} />
                <Route path="content" element={<ContentPage />} />
                <Route path="content-library" element={<ContentLibraryPage />} />
                <Route path="notifications" element={<NotificationsPage />} />
                <Route path="support" element={<SupportPage />} />
                <Route path="automations" element={<AutomationsPage />} />
                <Route path="insights" element={<InsightsPage />} />
                <Route path="whatsapp" element={<WhatsAppPage />} />
                <Route path="leads" element={<LeadsPage />} />
                <Route path="crm" element={<Navigate to="/business/leads" replace />} />
                <Route path="shop" element={<ShopPage />} />
                <Route path="creators" element={<CreatorsPage />} />
                <Route path="brand-safety" element={<BrandSafetyPage />} />
                <Route path="live" element={<LivePage />} />
                <Route path="inspiration" element={<InspirationPage />} />
                <Route path="ads" element={<AdsPage />} />
                <Route path="team" element={<SpacePanelPage section="team" title="Team & roles" subtitle="Who can post, reply and manage" />} />
                <Route path="settings" element={<SpacePanelPage section="settings" title="Settings" subtitle="Business page settings" />} />
                <Route path="verification" element={<SpacePanelPage section="verification" title="Verification" subtitle="Get the verified badge on your Space" />} />
                <Route path="*" element={<Navigate to="/business" replace />} />
              </Route>
            </Route>
            <Route path="*" element={<Navigate to="/business" replace />} />
          </Routes>
        </Suspense>
      </BrowserRouter>
    </QueryClientProvider>
  );
}

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <App />
  </StrictMode>,
);
