"use client";
import { useContext, useState, useEffect, useOptimistic, startTransition, useRef, } from "react";
import { NavigationStoreContext } from "./context.js";
/**
 * Shallow equality check for selector results
 */
function shallowEqual(a, b) {
    if (Object.is(a, b))
        return true;
    if (typeof a !== "object" ||
        a === null ||
        typeof b !== "object" ||
        b === null) {
        return false;
    }
    const keysA = Object.keys(a);
    const keysB = Object.keys(b);
    if (keysA.length !== keysB.length)
        return false;
    for (const key of keysA) {
        if (!Object.hasOwn(b, key) ||
            !Object.is(a[key], b[key])) {
            return false;
        }
    }
    return true;
}
/**
 * Convert derived state to public version (strips inflightActions)
 */
function toPublicState(state) {
    const { inflightActions: _, ...publicState } = state;
    return publicState;
}
export function useNavigation(selector) {
    const ctx = useContext(NavigationStoreContext);
    if (!ctx) {
        throw new Error("useNavigation must be used within NavigationStoreContext.Provider");
    }
    // Base state for useOptimistic
    const [baseValue, setBaseValue] = useState(() => {
        const publicState = toPublicState(ctx.eventController.getState());
        return selector ? selector(publicState) : publicState;
    });
    const prevState = useRef(baseValue);
    // useOptimistic allows immediate updates during transitions/actions
    const [value, setOptimisticValue] = useOptimistic(baseValue);
    // Store selector in a ref to avoid re-subscribing when an inline
    // function is passed (its identity changes every render).
    const selectorRef = useRef(selector);
    selectorRef.current = selector;
    // Subscribe to event controller state changes (only runs on client)
    useEffect(() => {
        // Subscribe to updates from event controller
        return ctx.eventController.subscribe(() => {
            const currentState = ctx.eventController.getState();
            const publicState = toPublicState(currentState);
            const nextSelected = selectorRef.current
                ? selectorRef.current(publicState)
                : publicState;
            // Check if selected value has changed
            if (!shallowEqual(nextSelected, prevState.current)) {
                prevState.current = nextSelected;
                // Check if any actions are in progress for optimistic updates
                const hasInflightActions = ctx.eventController.getInflightActions().size > 0;
                if (hasInflightActions || publicState.state !== "idle") {
                    // Use optimistic update for immediate feedback during transitions
                    startTransition(() => {
                        setOptimisticValue(nextSelected);
                    });
                }
                // Always update base state so UI reflects current state
                setBaseValue(nextSelected);
            }
        });
    }, []);
    // If no selector, include navigation methods
    if (!selector) {
        return {
            ...value,
            navigate: ctx.navigate,
            refresh: ctx.refresh,
        };
    }
    return value;
}
//# sourceMappingURL=use-navigation.js.map