"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { forwardRef, useCallback, useContext, useRef } from "react";
import { NavigationStoreContext } from "./context.js";
import { LinkContext } from "./use-link-status.js";
import { isLocationStateEntry, resolveLocationStateEntries, } from "./location-state.js";
// Track prefetched URLs to avoid duplicate <link> elements
const prefetchedUrls = new Set();
/**
 * Inject a <link rel="prefetch"> element into the document head
 * for the given URL with RSC partial request parameters.
 */
function prefetchUrl(url, segmentIds) {
    if (prefetchedUrls.has(url))
        return;
    prefetchedUrls.add(url);
    // Build RSC partial URL with segment IDs
    const targetUrl = new URL(url, window.location.origin);
    targetUrl.searchParams.set("_rsc_partial", "true");
    if (segmentIds.length > 0) {
        targetUrl.searchParams.set("_rsc_segments", segmentIds.join(","));
    }
    // Inject <link rel="prefetch"> into head
    const link = document.createElement("link");
    link.rel = "prefetch";
    link.href = targetUrl.toString();
    link.as = "fetch";
    document.head.appendChild(link);
}
/**
 * Check if URL is external (different origin)
 */
function isExternalUrl(href) {
    // Protocol-relative URLs
    if (href.startsWith("//"))
        return true;
    // Absolute URLs
    if (href.startsWith("http://") || href.startsWith("https://")) {
        try {
            return new URL(href).origin !== window.location.origin;
        }
        catch {
            return false;
        }
    }
    // Special protocols (mailto, tel, etc.)
    if (/^[a-z][a-z0-9+.-]*:/i.test(href)) {
        return true;
    }
    return false;
}
/**
 * Type-safe Link component for SPA navigation
 *
 * Works with router.reverse() for type-safe URLs:
 * ```tsx
 * <Link to={router.reverse("shop.products.detail", { slug: "my-product" })}>
 *   View Product
 * </Link>
 * ```
 *
 * Also supports regular URLs:
 * ```tsx
 * <Link to="/about">About</Link>
 * <Link to="https://example.com">External</Link>
 * ```
 */
export const Link = forwardRef(function Link({ to, replace = false, scroll = true, reloadDocument = false, prefetch = "none", state, children, onClick, ...props }, ref) {
    const ctx = useContext(NavigationStoreContext);
    const isExternal = isExternalUrl(to);
    // Use ref to always get the latest state/getter without adding to useCallback deps
    // This enables just-in-time state resolution without causing re-renders
    const stateRef = useRef(state);
    stateRef.current = state;
    const handleClick = useCallback((e) => {
        // Call user's onClick handler first
        onClick?.(e);
        // If user prevented default, respect that
        if (e.defaultPrevented)
            return;
        // External links - let browser handle normally
        if (isExternal)
            return;
        // Force document navigation if requested
        if (reloadDocument)
            return;
        // Allow modifier keys for opening in new tab/window
        if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
            return;
        // Check for download attribute
        if (e.currentTarget.hasAttribute("download"))
            return;
        // Check for target attribute
        const target = e.currentTarget.target;
        if (target && target !== "_self")
            return;
        // Prevent default and use SPA navigation
        e.preventDefault();
        // Stop propagation to prevent link-interceptor from also handling this
        e.stopPropagation();
        if (ctx?.navigate) {
            // Resolve state just-in-time based on format
            let resolvedState;
            const currentState = stateRef.current;
            if (Array.isArray(currentState) && currentState.length > 0 && isLocationStateEntry(currentState[0])) {
                // Type-safe LocationStateEntry[] - resolve each entry into keyed object
                resolvedState = resolveLocationStateEntries(currentState);
            }
            else if (typeof currentState === "function") {
                // Legacy getter function
                resolvedState = currentState();
            }
            else {
                // Legacy static value
                resolvedState = currentState;
            }
            ctx.navigate(to, { replace, scroll, state: resolvedState });
        }
    }, [to, isExternal, reloadDocument, replace, scroll, ctx, onClick]);
    const handleMouseEnter = useCallback(() => {
        if (prefetch === "hover" && !isExternal && ctx?.store) {
            const segmentState = ctx.store.getSegmentState();
            prefetchUrl(to, segmentState.currentSegmentIds);
        }
    }, [prefetch, to, isExternal, ctx]);
    return (_jsx("a", { ref: ref, href: to, onClick: handleClick, onMouseEnter: handleMouseEnter, "data-link-component": true, "data-external": isExternal ? "" : undefined, "data-scroll": scroll === false ? "false" : undefined, "data-replace": replace ? "true" : undefined, ...props, children: _jsx(LinkContext.Provider, { value: to, children: children }) }));
});
//# sourceMappingURL=Link.js.map