// IMPORTANT: Polyfills must be imported FIRST
import { getCurrentWindow } from '@tauri-apps/api/window';
import 'katex/dist/katex.min.css';
import React from 'react';
import ReactDOM from 'react-dom/client';

import App from './App';
import './index.css';
import { getCoreStateSnapshot } from './lib/coreState/store';
import MascotWindowApp from './mascot/MascotWindowApp';
import NotchApp from './notch/NotchApp';
import OverlayApp from './overlay/OverlayApp';
import './polyfills';
import { initGA, initSentry, startUiInteractionTracking, trackEvent } from './services/analytics';
import { setStoreForApiClient } from './services/apiClient';
import { primeActiveUserId } from './store/userScopedStorage';
import './styles/code-highlight.css';
import './styles/theme.css';
import { APP_VERSION } from './utils/config';
import { setupDesktopDeepLinkListener } from './utils/desktopDeepLinkListener';
import { missingHashRedirectTarget } from './utils/hashRouterBootstrap';
import { getActiveUserIdFromCore } from './utils/tauriCommands';
import { isTauri as tauriRuntimeAvailable } from './utils/tauriCommands/common';

setStoreForApiClient(() => getCoreStateSnapshot().snapshot.sessionToken);

// The floating mascot is hosted in a native macOS NSPanel + WKWebView
// that lives OUTSIDE Tauri's runtime (the vendored tauri-cef can't render
// transparent windowed-mode browsers). That webview can't read a Tauri
// window label, so the Rust shell appends `?window=mascot` to the URL it
// loads. Detect it via the URL param so we can skip `getCurrentWindow()`
// — which would either throw or trigger the CEF IPC-bootstrap gap that
// `tauriRuntimeAvailable()` (= the hardened `isTauri()`) now guards
// against by reading `window.__TAURI_INTERNALS__.invoke`.
const urlWindowParam = (() => {
  try {
    return new URLSearchParams(window.location.search).get('window');
  } catch {
    return null;
  }
})();
const isMascotWindow = urlWindowParam === 'mascot';
const isNotchWindow = urlWindowParam === 'notch';
const currentWindowLabel = isMascotWindow
  ? 'mascot'
  : isNotchWindow
    ? 'notch'
    : tauriRuntimeAvailable()
      ? getCurrentWindow().label
      : 'main';
const isOverlayWindow = currentWindowLabel === 'overlay';
const isStandaloneWindow = isOverlayWindow || isMascotWindow || isNotchWindow;

const ensureDefaultHashRoute = () => {
  const hash = window.location.hash;
  if (!hash || hash === '#') {
    window.location.replace(
      missingHashRedirectTarget(window.location.pathname, window.location.search)
    );
    return;
  }
  if (!hash.startsWith('#/')) {
    window.location.hash = '/';
  }
};

// Initialize Sentry and GA early (before React renders)
initSentry();
initGA();
if (!isStandaloneWindow) {
  startUiInteractionTracking();
  trackEvent('app_open', { version: APP_VERSION });
}
document.documentElement.dataset.window = currentWindowLabel;

if (!isStandaloneWindow) {
  ensureDefaultHashRoute();

  // Deep link listener — try/catch handles non-Tauri environments
  setupDesktopDeepLinkListener().catch(err => {
    console.error('[DeepLink] setup error:', err);
  });
}

// Prime `userScopedStorage` from the Rust core's `active_user.toml`
// BEFORE redux-persist hydrates. The previous localStorage-only seed was
// bound to the per-user CEF profile dir and went stale across the
// restart-driven user flips that #900 introduced, so the new process
// would read the previous user's namespace, mis-detect a flip, and bounce
// into a second restart. Reading the Rust state up front pins the right
// namespace from the first storage call. (#900)
function bootRender() {
  const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
  const tree = isMascotWindow ? (
    <MascotWindowApp />
  ) : isNotchWindow ? (
    <NotchApp />
  ) : isOverlayWindow ? (
    <OverlayApp />
  ) : (
    <App />
  );
  root.render(<React.StrictMode>{tree}</React.StrictMode>);
}

// The mascot and notch windows live in native WKWebViews (no Tauri IPC), so
// `getActiveUserIdFromCore()` would just reject after a roundtrip and
// delay first paint for nothing. Skip the bootstrap entirely in those
// paths — neither UI reads user-scoped storage.
const activeUserBootstrap =
  isMascotWindow || isNotchWindow
    ? Promise.resolve<string | null>(null)
    : getActiveUserIdFromCore();

activeUserBootstrap
  .then(id => primeActiveUserId(id))
  .catch(() => primeActiveUserId(null))
  .finally(bootRender);
