/**
 * Type definitions for Next.js integration helpers.
 *
 * These types define the options and props for the `createCatchAllPage()` factory,
 * which simplifies catch-all routing for Riverbank CMS sites.
 */
import type { ReactNode } from 'react';
import type { RiverbankClient } from '../client/types';
import type { RiverbankSiteConfig } from '../config/types';
import type { Theme } from '../contracts';
import type { BlockOverrides } from '../rendering/overrides';
import type { Metadata } from '../metadata/generatePageMetadata';
import type { LoadContentResult } from '../rendering/helpers/loadContent';
/**
 * Context passed to escape hatch callbacks.
 */
export interface CatchAllContext {
    /** Loaded content (page or entry) */
    content: LoadContentResult;
    /** Resolved URL path (e.g., '/about', '/blog/my-post') */
    path: string;
    /** Whether preview mode is enabled */
    preview: boolean;
    /**
     * Whether the SDK page renderer should wrap content in ThemeScope.
     *
     * This is the same `useThemeScope` value passed to `createCatchAllPage()`.
     * Preview mode should mirror this so SDK sites that fully own their styling
     * don't accidentally get CMS theme styling applied only while editing.
     */
    useThemeScope: boolean;
    /** Search parameters from the URL (for filtering, pagination, etc.) */
    searchParams: Record<string, string | string[] | undefined>;
}
/**
 * Configuration for runtime theme switching when `themes` is provided.
 *
 * V1 supports query-param switching only to keep the surface area small and
 * Edge-safe. Cookie/header switching can be added later if needed.
 */
export interface ThemeSwitchConfigV1 {
    /**
     * Query parameter name used to select a theme key from `themes`.
     *
     * @default 'theme'
     * @example '?theme=seasonal'
     */
    queryParam?: string;
    /**
     * Default theme key when the query param is missing.
     *
     * If omitted, falls back to `config.activeTheme ?? 'current'`.
     */
    defaultKey?: string;
    /**
     * Behavior when the selected theme key is not present in `themes`.
     *
     * - 'fallback': use defaultKey (warn in development)
     * - 'error': treat as not found (404)
     *
     * @default 'fallback'
     */
    onInvalidKey?: 'fallback' | 'error';
}
/**
 * Context passed to `getTheme` resolver.
 */
export interface ThemeResolverContext extends CatchAllContext {
    /** Site config from `createCatchAllPage({ config })` */
    config: RiverbankSiteConfig;
    /** Optional key selected from `themes` (when applicable) */
    themeKey?: string;
}
type CatchAllThemeOptions = {
    /**
     * Default behavior: use the CMS theme from `loadContent()`.
     * If `config.themeSource === 'local'`, you must supply a theme via
     * `theme`, `themes`, or `getTheme`.
     */
    theme?: never;
    themes?: never;
    themeSwitch?: never;
    getTheme?: never;
} | {
    /** Use a single, static theme object for all requests. */
    theme: Theme;
    themes?: never;
    themeSwitch?: never;
    getTheme?: never;
} | {
    /**
     * Provide multiple themes and optionally enable runtime switching.
     *
     * If `themeSwitch` is omitted, the theme key defaults to
     * `config.activeTheme ?? 'current'`.
     */
    themes: Record<string, Theme>;
    themeSwitch?: ThemeSwitchConfigV1;
    theme?: never;
    getTheme?: never;
} | {
    /**
     * Escape hatch for per-request theme resolution.
     *
     * Note: this runs after content is loaded (so the resolver receives
     * `context.content`). If you need to switch themes based purely on
     * URL query params, prefer `themes + themeSwitch`.
     */
    getTheme: (context: ThemeResolverContext) => Theme | Promise<Theme>;
    theme?: never;
    themes?: never;
    themeSwitch?: never;
};
/**
 * Options for the `createCatchAllPage()` factory.
 *
 * @example Basic usage
 * ```tsx
 * const { Page, generateMetadata } = createCatchAllPage({
 *   getClient: getRiverbankClient,
 *   config,
 *   blockOverrides: { hero: MyCustomHero },
 * });
 * ```
 *
 * @example With maintenance mode
 * ```tsx
 * const { Page, generateMetadata } = createCatchAllPage({
 *   getClient,
 *   config,
 *   beforeRender: async () => {
 *     if (process.env.MAINTENANCE_MODE === 'true') {
 *       return <MaintenancePage />;
 *     }
 *     return null; // Continue with normal rendering
 *   },
 * });
 * ```
 */
export type CreateCatchAllPageOptions = {
    /**
     * Function that returns the Riverbank client.
     * Called fresh on each request to support different caching strategies.
     */
    getClient: () => RiverbankClient;
    /**
     * Site configuration from `defineConfig()`.
     * Provides siteId and content type routing information.
     */
    config: RiverbankSiteConfig;
    /**
     * Override preview mode detection.
     *
     * By default, preview mode is automatically detected from the client's API key:
     * - `bld_live_sk_*` or `bld_test_sk_*` → published content (preview: false)
     * - `bld_preview_sk_*` → draft content (preview: true)
     *
     * This automatic detection eliminates the need for manual coordination
     * between API key selection and preview mode configuration.
     *
     * Only set this option if you need to override the automatic detection
     * (e.g., for testing or advanced use cases).
     *
     * @example Automatic detection (recommended)
     * ```tsx
     * // builder-client.ts - use preview key for staging
     * const apiKey = process.env.NODE_ENV === 'staging'
     *   ? 'bld_preview_sk_...'
     *   : 'bld_live_sk_...';
     *
     * export const getRiverbankClient = () => createRiverbankClient({ apiKey, ... });
     *
     * // page.tsx - preview mode is auto-detected from key type
     * const { Page } = createCatchAllPage({
     *   getClient: getRiverbankClient,
     *   config,
     *   // No preview option needed - it's inferred from the API key!
     * });
     * ```
     */
    preview?: boolean;
    /**
     * Custom block component overrides for rendering.
     * Keys can be full block kind ("block.hero") or short form ("hero").
     */
    blockOverrides?: BlockOverrides;
    /**
     * Override site URL for metadata generation.
     * Defaults to `config.liveUrl` or `config.previewUrl` based on preview mode.
     */
    siteUrl?: string;
    /**
     * Intercept before rendering to implement maintenance mode, access control, etc.
     *
     * Return a React node to short-circuit rendering, or `null` to continue
     * with normal page/entry rendering.
     *
     * @example Maintenance mode
     * ```tsx
     * beforeRender: async () => {
     *   if (process.env.MAINTENANCE_MODE === 'true') {
     *     return <MaintenancePage />;
     *   }
     *   return null;
     * }
     * ```
     *
     * @example Access control
     * ```tsx
     * beforeRender: async ({ path }) => {
     *   if (path.startsWith('/members')) {
     *     const session = await getSession();
     *     if (!session) return <LoginPage redirect={path} />;
     *   }
     *   return null;
     * }
     * ```
     */
    beforeRender?: (context: CatchAllContext) => ReactNode | null | Promise<ReactNode | null>;
    /**
     * Custom metadata generator. If provided, replaces default metadata generation.
     *
     * Use this when you need full control over SEO metadata, such as adding
     * product-specific Open Graph tags for e-commerce sites.
     *
     * @example Custom product metadata
     * ```tsx
     * customMetadata: async ({ content }) => {
     *   if (isEntryContent(content) && content.entry.type === 'product') {
     *     return {
     *       title: `${content.entry.title} | Shop`,
     *       openGraph: { type: 'product' },
     *     };
     *   }
     *   // Use default for other content types
     *   return generatePageMetadata({ page, site, path, siteUrl });
     * }
     * ```
     */
    customMetadata?: (context: CatchAllContext) => Metadata | Promise<Metadata>;
    /**
     * Wrapper component around rendered content.
     *
     * Useful for adding analytics scripts, error boundaries, or layout wrappers
     * that should wrap all page content.
     *
     * @example Analytics wrapper
     * ```tsx
     * wrapper: ({ children }) => (
     *   <>
     *     {children}
     *     <AnalyticsScript siteId={config.siteId} />
     *   </>
     * )
     * ```
     */
    wrapper?: (props: {
        children: ReactNode;
    }) => ReactNode | Promise<ReactNode>;
    /**
     * Wrap page content in ThemeScope to inject theme CSS variables and styles.
     * Enable this to use built-in theme styling from the CMS.
     * Disable if you're bringing your own styles.
     *
     * @default false
     */
    useThemeScope?: boolean;
    /**
     * Enable portal authentication for the reserved `/portal` customer route.
     *
     * When enabled, reads the portal session token from the httpOnly cookie
     * set by the portal callback route so the dedicated portal surface can make
     * authenticated API calls.
     *
     * Requires setting up portal routes in your app:
     * - `/api/portal/callback` using `handlePortalCallback()`
     * - `/api/portal/logout` using `handlePortalLogout()`
     *
     * @default false
     *
     * @example
     * ```tsx
     * const { Page } = createCatchAllPage({
     *   getClient,
     *   config,
     *   enablePortal: true,
     * });
     * ```
     */
    enablePortal?: boolean;
} & CatchAllThemeOptions;
/**
 * Next.js page props for catch-all routes.
 *
 * This matches the signature expected by Next.js 15+ App Router pages
 * with the `[[...slug]]` pattern.
 */
export interface CatchAllPageProps {
    /** Route parameters containing the slug segments */
    params: Promise<{
        slug?: string[];
    }>;
    /** Optional search parameters from the URL */
    searchParams?: Promise<Record<string, string | string[] | undefined>>;
}
/**
 * Result of the `createCatchAllPage()` factory.
 */
export interface CreateCatchAllPageResult {
    /**
     * React component to use as the default export of your catch-all page.
     *
     * @example
     * ```tsx
     * const { Page, generateMetadata } = createCatchAllPage({ ... });
     * export default Page;
     * ```
     */
    Page: (props: CatchAllPageProps) => Promise<ReactNode>;
    /**
     * Metadata generation function for Next.js `generateMetadata`.
     *
     * @example
     * ```tsx
     * const { Page, generateMetadata } = createCatchAllPage({ ... });
     * export { generateMetadata };
     * ```
     */
    generateMetadata: (props: CatchAllPageProps) => Promise<Metadata>;
}
export {};
