/**
 * Dedicated entry for the new-stack project app (w.html), served at
 * `/<worldId>/<projectId>` (see services/world/worldUrl.ts).
 *
 * Patchwork-shaped cold start (see design/patchwork-reference.md §1, and
 * patchwork's own site.ts:181-203):
 *  - LEAN: this entry mounts ONLY the router + WorldPage. It does NOT import
 *    the legacy SPA shell (App.tsx) — no Auth/Org providers, no legacy RepoProvider,
 *    no @linear/sdk, no @pierre/trees, no connectors. Those are the bulk of the
 *    old cold-start weight and this surface needs none of them.
 *  - WASM AS FETCHED ASSETS, not inlined base64: the tab Repo needs both automerge
 *    core and subduction wasm on the main thread (the fork's Repo builds a
 *    MemorySigner from subduction wasm unconditionally — Repo.js:105 — so this is
 *    unavoidable and patchwork does it too). But we load them as real `.wasm`
 *    assets (`?url` → Vite emits + hashes them, w.html <link rel=preload>s them)
 *    and `fetch()` the bytes, instead of shipping a ~5MB base64 string in a JS
 *    chunk that must be downloaded whole then atob-decoded on the main thread.
 *  - SKELETON FIRST: w.html paints a static skeleton before this module's
 *    top-level await resolves, so the blank screen ends before the wasm compile
 *    (patchwork's showLoadingAnimation, site.ts:199, runs before init at :202).
 *
 * The worker (shared-repo.worker.ts) still inits its own wasm independently; that
 * runs off the main thread and does not gate first paint.
 */

// `?url`: import the wasm as a hashed asset URL, not as a module/base64 blob.
import automergeWasmUrl from '@automerge/automerge/automerge.wasm?url'
import { initializeWasm } from '@automerge/automerge-repo/slim'
import { initSync as initSubduction } from '@automerge/automerge-subduction/slim'
import subductionWasmUrl from '@automerge/automerge-subduction/wasm?url'
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import {
  BrowserRouter,
  Navigate,
  Route,
  Routes,
  useLocation,
} from 'react-router-dom'
import '../../styles/globals.css'
import { trackWasm } from '../../services/memory/realmReport'
import { consumeSharingSignIn } from '../../services/sharing/account'
import { stashInviteFromUrl } from '../../services/sharing/pendingInvite'
import { adoptWorldFromPath } from '../../services/world/worldUrl'
import { LegacyProjectRedirect, WorldPage } from './WorldPage'

// Scrub the account callback before any repo or network connection starts.
if (import.meta.env.VITE_MOD_KEYHIVE === '1') {
  try {
    stashInviteFromUrl()
    consumeSharingSignIn()
  } catch (error) {
    const message = document.createElement('p')
    message.setAttribute('role', 'alert')
    message.textContent =
      error instanceof Error ? error.message : 'Sign-in failed'
    document.body.prepend(message)
  }
}

// Fetch both wasm binaries in parallel (w.html preloads them, so these usually
// resolve from the preload cache), then init on the main thread before any Repo
// is constructed. Bytes, not base64 — no atob, no ~5MB main-thread decode.
const [automergeBytes, subductionBytes] = await Promise.all([
  fetch(automergeWasmUrl).then((r) => r.arrayBuffer()),
  fetch(subductionWasmUrl).then((r) => r.arrayBuffer()),
])
// Tracked, so the memory report can name each wasm memory (RFC 0346 S2).
await trackWasm('automerge', () =>
  initializeWasm(new Uint8Array(automergeBytes)),
)
await trackWasm('subduction', () =>
  initSubduction({ module: new Uint8Array(subductionBytes) }),
)

// Before anything renders, so every reader of the pointer sees the World the
// URL names from its first read.
adoptWorldFromPath(window.location.pathname)

createRoot(document.getElementById('root') as HTMLElement).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<WorldPage />} />
        <Route path="/w" element={<LegacyWorldRedirect />} />
        <Route path="/w/:projectId" element={<LegacyProjectRedirect />} />
        <Route path="/:worldId" element={<WorldPage />} />
        <Route path="/:worldId/:projectId" element={<WorldPage />} />
        <Route path="*" element={<Navigate to="/" replace />} />
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

/** The old bare `/w`: the root, query and all. */
function LegacyWorldRedirect() {
  const { search } = useLocation()
  return <Navigate to={`/${search}`} replace />
}
