import { jsx as _jsx } from "react/jsx-runtime";
import { renderSegments as baseRenderSegments, } from "../segment-system.js";
import { createNavigationStore, generateHistoryKey, } from "./navigation-store.js";
import { createEventController } from "./event-controller.js";
import { createNavigationClient } from "./navigation-client.js";
import { createServerActionBridge } from "./server-action-bridge.js";
import { createNavigationBridge } from "./navigation-bridge.js";
import { NavigationProvider, initHandleDataSync, initSegmentsSync } from "./react/index.js";
import { initThemeConfigSync } from "../theme/theme-context.js";
// Module-level state for the initialized app
let browserAppContext = null;
/**
 * Initialize the browser app. Must be called before rendering RSCRouter.
 *
 * This function:
 * - Loads the initial RSC payload from the stream
 * - Creates the navigation store and event controller
 * - Sets up action and navigation bridges
 * - Configures HMR support
 */
export async function initBrowserApp(options) {
    const { rscStream, deps, storeOptions, linkInterception = true, themeConfig, initialTheme } = options;
    // Load initial payload from SSR-injected __FLIGHT_DATA__
    const initialPayload = await deps.createFromReadableStream(rscStream);
    // Extract themeConfig and initialTheme from payload if not explicitly provided
    // This allows virtual entries to work without importing the router
    const effectiveThemeConfig = themeConfig ?? initialPayload.metadata?.themeConfig ?? null;
    const effectiveInitialTheme = initialTheme ?? initialPayload.metadata?.initialTheme;
    // Get initial segments and compute history key from current URL
    const initialSegments = (initialPayload.metadata?.segments ??
        []);
    const initialHistoryKey = generateHistoryKey(window.location.href);
    // Create navigation store with history-based caching
    const store = createNavigationStore({
        initialLocation: window.location,
        initialSegmentIds: initialSegments.map((s) => s.id),
        initialHistoryKey,
        initialSegments,
        ...(storeOptions?.cacheSize && { cacheSize: storeOptions.cacheSize }),
    });
    // Create event controller for reactive state management
    const eventController = createEventController({
        initialLocation: new URL(window.location.href),
    });
    // Initialize segments state BEFORE hydration to avoid mismatch
    initSegmentsSync(initialPayload.metadata?.matched, initialPayload.metadata?.pathname);
    // Initialize theme config for MetaTags (must match SSR state)
    initThemeConfigSync(effectiveThemeConfig);
    // Initialize event controller with segment order (even without handles)
    eventController.setHandleData({}, initialPayload.metadata?.matched);
    // Initialize handle data from initial payload BEFORE hydration
    // This ensures useHandle returns correct data during hydration to avoid mismatch
    // The handles property is an async generator that yields on each push
    if (initialPayload.metadata?.handles) {
        const handlesGenerator = initialPayload.metadata.handles;
        let lastHandleData = {};
        for await (const handleData of handlesGenerator) {
            lastHandleData = handleData;
        }
        // Initialize both event controller AND module-level SSR state for hydration compatibility
        eventController.setHandleData(lastHandleData, initialPayload.metadata?.matched);
        initHandleDataSync(lastHandleData, initialPayload.metadata?.matched);
        // Update the initial cache entry with the processed handleData
        // The cache entry was created by createNavigationStore but without handleData
        store.updateCacheHandleData(initialHistoryKey, lastHandleData);
    }
    // Create composable utilities
    const client = createNavigationClient(deps);
    // Extract rootLayout and version from metadata for browser-side re-renders
    const rootLayout = initialPayload.metadata?.rootLayout;
    const version = initialPayload.metadata?.version;
    // Create a bound renderSegments that includes rootLayout
    const renderSegments = (segments, options) => baseRenderSegments(segments, { ...options, rootLayout });
    // Setup server action bridge
    const actionBridge = createServerActionBridge({
        store,
        eventController,
        client,
        deps,
        onUpdate: (update) => store.emitUpdate(update),
        renderSegments,
        version,
    });
    actionBridge.register();
    // Setup navigation bridge
    const navigationBridge = createNavigationBridge({
        store,
        eventController,
        client,
        onUpdate: (update) => store.emitUpdate(update),
        renderSegments,
        version,
    });
    // Optionally enable global link interception
    if (linkInterception) {
        navigationBridge.registerLinkInterception();
    }
    // Build initial tree with rootLayout
    const initialTree = renderSegments(initialPayload.metadata.segments);
    // Setup HMR
    if (import.meta.hot) {
        import.meta.hot.on("rsc:update", async () => {
            console.log("[RSCRouter] HMR: Server update, refetching RSC");
            const handle = eventController.startNavigation(window.location.href, {
                replace: true,
            });
            const streamingToken = handle.startStreaming();
            try {
                const { payload, streamComplete } = await client.fetchPartial({
                    targetUrl: window.location.href,
                    segmentIds: [],
                    previousUrl: store.getSegmentState().currentUrl,
                    hmr: true,
                });
                if (payload.metadata?.isPartial) {
                    const segments = payload.metadata.segments || [];
                    const matched = payload.metadata.matched || [];
                    store.setSegmentIds(matched);
                    store.setCurrentUrl(window.location.href);
                    const historyKey = generateHistoryKey(window.location.href);
                    store.setHistoryKey(historyKey);
                    const currentHandleData = eventController.getHandleState().data;
                    store.cacheSegmentsForHistory(historyKey, segments, currentHandleData);
                    store.emitUpdate({
                        root: renderSegments(segments),
                        metadata: payload.metadata,
                    });
                }
                await streamComplete;
            }
            finally {
                streamingToken.end();
            }
            handle.complete(new URL(window.location.href));
            console.log("[RSCRouter] HMR: RSC stream complete");
        });
    }
    // Store context for RSCRouter component
    const context = {
        store,
        eventController,
        bridge: navigationBridge,
        initialPayload,
        initialTree,
        themeConfig: effectiveThemeConfig,
        initialTheme: effectiveInitialTheme,
        warmupEnabled: initialPayload.metadata?.warmupEnabled ?? true,
    };
    browserAppContext = context;
    return context;
}
/**
 * Get the browser app context. Throws if initBrowserApp hasn't been called.
 */
export function getBrowserAppContext() {
    if (!browserAppContext) {
        throw new Error("RSCRouter: initBrowserApp() must be called before rendering RSCRouter");
    }
    return browserAppContext;
}
/**
 * Reset the browser app context (for testing)
 */
export function resetBrowserAppContext() {
    browserAppContext = null;
}
/**
 * RSCRouter component - renders the RSC router with all internal wiring.
 *
 * Must be called after initBrowserApp() has completed.
 *
 * @example
 * ```tsx
 * import { initBrowserApp, RSCRouter } from "rsc-router/browser";
 * import { rscStream } from "rsc-html-stream/client";
 * import * as rscBrowser from "@vitejs/plugin-rsc/browser";
 *
 * async function main() {
 *   await initBrowserApp({ rscStream, deps: rscBrowser });
 *
 *   hydrateRoot(
 *     document,
 *     <React.StrictMode>
 *       <RSCRouter />
 *     </React.StrictMode>
 *   );
 * }
 * main();
 * ```
 */
export function RSCRouter(_props) {
    const { store, eventController, bridge, initialPayload, initialTree, themeConfig, initialTheme, warmupEnabled } = getBrowserAppContext();
    return (_jsx(NavigationProvider, { store: store, eventController: eventController, initialPayload: { ...initialPayload, root: initialTree }, bridge: bridge, themeConfig: themeConfig, initialTheme: initialTheme, warmupEnabled: warmupEnabled }));
}
//# sourceMappingURL=rsc-router.js.map