"use client";
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * Component to render collected meta descriptors in the document head.
 *
 * Supports both sync and async meta descriptors. Async descriptors
 * (Promise<MetaDescriptorBase>) are resolved using React's use() hook.
 *
 * When theme is enabled in the router config, MetaTags also renders
 * the theme initialization script to prevent FOUC (flash of unstyled content).
 *
 * @example
 * ```tsx
 * function RootLayout() {
 *   return (
 *     <html lang="en" suppressHydrationWarning>
 *       <head>
 *         <MetaTags />
 *       </head>
 *       <body>...</body>
 *     </html>
 *   );
 * }
 * ```
 */
import { use } from "react";
import { useHandle } from "../browser/react/use-handle.js";
import { Meta } from "./meta.js";
import { getSSRThemeConfig } from "../theme/theme-context.js";
import { generateThemeScript } from "../theme/theme-script.js";
// Type guards for MetaDescriptorBase variants
function hasCharSet(d) {
    return "charSet" in d && d.charSet === "utf-8";
}
function hasTitle(d) {
    return "title" in d && typeof d.title === "string";
}
function hasNameContent(d) {
    return "name" in d && "content" in d &&
        typeof d.name === "string" &&
        typeof d.content === "string";
}
function hasPropertyContent(d) {
    return "property" in d && "content" in d &&
        typeof d.property === "string" &&
        typeof d.content === "string";
}
function hasHttpEquivContent(d) {
    return "httpEquiv" in d && "content" in d &&
        typeof d.httpEquiv === "string" &&
        typeof d.content === "string";
}
function hasScriptLdJson(d) {
    return "script:ld+json" in d;
}
function hasTagName(d) {
    return "tagName" in d && (d.tagName === "meta" || d.tagName === "link");
}
/**
 * Check if a value is a Promise.
 */
function isPromise(value) {
    return value !== null && typeof value === "object" && "then" in value;
}
/**
 * Render a single meta descriptor as a React element.
 */
function renderMetaDescriptor(descriptor, index) {
    // charset
    if (hasCharSet(descriptor)) {
        return _jsx("meta", { charSet: descriptor.charSet }, "charSet");
    }
    // title
    if (hasTitle(descriptor)) {
        return _jsx("title", { children: descriptor.title }, "title");
    }
    // name + content (description, viewport, etc.)
    if (hasNameContent(descriptor)) {
        return (_jsx("meta", { name: descriptor.name, content: descriptor.content }, `name-${descriptor.name}`));
    }
    // property + content (Open Graph, etc.)
    if (hasPropertyContent(descriptor)) {
        return (_jsx("meta", { property: descriptor.property, content: descriptor.content }, `property-${descriptor.property}`));
    }
    // http-equiv + content
    if (hasHttpEquivContent(descriptor)) {
        return (_jsx("meta", { httpEquiv: descriptor.httpEquiv, content: descriptor.content }, `httpEquiv-${descriptor.httpEquiv}`));
    }
    // JSON-LD structured data
    if (hasScriptLdJson(descriptor)) {
        const json = JSON.stringify(descriptor["script:ld+json"]);
        return (_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: json } }, `ld-json-${index}`));
    }
    // Custom tagName (meta or link with arbitrary attributes)
    if (hasTagName(descriptor)) {
        const { tagName, ...rest } = descriptor;
        if (tagName === "link") {
            return _jsx("link", { ...rest }, `link-${index}`);
        }
        if (tagName === "meta") {
            return _jsx("meta", { ...rest }, `meta-${index}`);
        }
    }
    // Fallback: treat as meta attributes
    return _jsx("meta", { ...descriptor }, `meta-fallback-${index}`);
}
/**
 * Wrapper component to resolve a Promise<MetaDescriptorBase> using use().
 */
function AsyncMetaTag({ promise, index }) {
    const resolved = use(promise);
    return renderMetaDescriptor(resolved, index);
}
/**
 * Renders all collected meta descriptors from route handlers.
 *
 * Place this component inside the `<head>` element of your document.
 * It will automatically update when meta descriptors change during navigation.
 *
 * When theme is enabled in router config, also renders the theme initialization
 * script to prevent FOUC (flash of unstyled content).
 *
 * Async meta descriptors (Promise<MetaDescriptorBase>) are resolved using
 * React's use() hook. RSC streaming handles the Promise resolution.
 */
export function MetaTags() {
    const descriptors = useHandle(Meta);
    const themeConfig = getSSRThemeConfig();
    return (_jsxs(_Fragment, { children: [themeConfig && (_jsx("script", { dangerouslySetInnerHTML: { __html: generateThemeScript(themeConfig) } })), descriptors.map((descriptor, index) => {
                if (isPromise(descriptor)) {
                    return _jsx(AsyncMetaTag, { promise: descriptor, index: index }, `async-${index}`);
                }
                return renderMetaDescriptor(descriptor, index);
            })] }));
}
//# sourceMappingURL=MetaTags.js.map