import { APIEndpoints } from '@riverbankcms/api';
import * as react_jsx_runtime from 'react/jsx-runtime';
import { PageOutline, Theme, ThemeTokens, RouteMap, OccurrenceContextData, PageRenderer, BlockOverrides } from '@riverbankcms/blocks';
import { ResolvedBlockData } from '@riverbankcms/blocks/system/data';

type SiteResponse = NonNullable<APIEndpoints['getSite']['response']>;
type PageResponse = NonNullable<APIEndpoints['getContentByPath']['response']>;
type EntriesResponse = NonNullable<APIEndpoints['listPublishedEntries']['response']>;
type EntryResponse = NonNullable<APIEndpoints['getPublishedEntryPreview']['response']>;
type PublicFormResponse = NonNullable<APIEndpoints['getPublicFormById']['response']>;
type PublicBookingServicesResponse = NonNullable<APIEndpoints['getPublicBookingServices']['response']>;
type PublicEventsResponse = NonNullable<APIEndpoints['listPublicEvents']['response']>;
/**
 * Configuration for creating a Riverbank CMS client
 */
interface RiverbankClientConfig {
    /**
     * API key for authentication (format: bld_live_... or bld_test_...)
     */
    apiKey: string;
    /**
     * Base URL for the Riverbank CMS API (required; e.g. https://dashboard.example.com/api)
     */
    baseUrl: string;
    /**
     * Cache configuration
     */
    cache?: {
        /**
         * Enable caching (default: true)
         */
        enabled?: boolean;
        /**
         * Time-to-live for cached responses in seconds
         * @default 300 (5 minutes)
         */
        ttl?: number;
        /**
         * Maximum number of cached responses
         * @default 100
         */
        maxSize?: number;
    };
}
/**
 * Riverbank CMS client interface
 */
interface RiverbankClient {
    /**
     * Fetch site data by slug, domain, or ID
     */
    getSite(params: {
        slug?: string;
        domain?: string;
        id?: string;
    }): Promise<SiteResponse>;
    /**
     * Fetch a specific page by path
     *
     * @param params.preview - If true, returns draft content instead of published content (requires API key with site access)
     */
    getPage(params: {
        siteId: string;
        path: string;
        preview?: boolean;
    }): Promise<PageResponse>;
    /**
     * Fetch published content entries with optional pagination, sorting, and preview mode
     *
     * @param params.siteId - The site ID
     * @param params.contentType - The content type key (e.g., 'blog-post', 'product')
     * @param params.limit - Maximum number of entries to return
     * @param params.order - Sort order: 'newest' (published_at desc) or 'oldest' (published_at asc)
     * @param params.preview - If true, includes draft entries (requires API key with site access)
     * @param params.mode - 'query' for automatic fetching, 'manual' for specific entry IDs
     * @param params.entryIds - Array of entry IDs to fetch (only used when mode is 'manual')
     *
     * @example
     * ```ts
     * // Fetch latest 10 blog posts
     * const entries = await client.getEntries({
     *   siteId: 'site-id',
     *   contentType: 'blog-post',
     *   limit: 10,
     *   order: 'newest',
     * });
     *
     * // Fetch draft entries for preview
     * const drafts = await client.getEntries({
     *   siteId: 'site-id',
     *   contentType: 'blog-post',
     *   preview: true,
     * });
     *
     * // Fetch specific entries by ID (manual mode)
     * const specific = await client.getEntries({
     *   siteId: 'site-id',
     *   contentType: 'blog-post',
     *   mode: 'manual',
     *   entryIds: ['uuid-1', 'uuid-2'],
     * });
     * ```
     */
    getEntries(params: {
        siteId: string;
        contentType: string;
        limit?: number;
        /** Sort order for entries. 'order' uses custom ordering (default behavior). */
        order?: 'newest' | 'oldest' | 'title' | 'order';
        preview?: boolean;
        /** Selection mode: 'query' for automatic, 'manual' for specific entry IDs */
        mode?: 'query' | 'manual';
        /** Entry IDs to fetch when mode is 'manual' */
        entryIds?: string[];
    }): Promise<EntriesResponse>;
    /**
     * Fetch a specific content entry by slug
     */
    getEntry(params: {
        siteId: string;
        contentType: string;
        slug: string;
    }): Promise<EntryResponse>;
    /**
     * Fetch a public form definition by ID
     */
    getPublicFormById(params: {
        formId: string;
    }): Promise<PublicFormResponse>;
    /**
     * Fetch public booking services for a site
     */
    getPublicBookingServices(params: {
        siteId: string;
        ids?: string;
    }): Promise<PublicBookingServicesResponse>;
    /**
     * List public events for a site (optionally time-filtered)
     */
    listPublicEvents(params: {
        siteId: string;
        limit?: number;
        from?: string;
        to?: string;
        stage?: string;
    }): Promise<PublicEventsResponse>;
    /**
     * Force clear the cache
     */
    clearCache(): void;
}

/**
 * Server-side helper to fetch all data needed for <Page> component.
 *
 * Use this in server components, getServerSideProps, or API routes.
 */

/**
 * SDK config from API response (without siteId which is stripped at storage).
 * This is the runtime representation - for defining configs, use RiverbankSiteConfig.
 */
type RuntimeSdkConfig = NonNullable<SiteResponse['sdkConfig']>;

type PageProps = {
    page: PageOutline;
    theme: Theme;
    siteId: string;
    themeTokens?: ThemeTokens;
    resolvedData?: ResolvedBlockData;
    routeMap?: RouteMap;
    /**
     * SDK site configuration containing theme palette overrides.
     * When provided, the SDK palette tokens are merged into the theme tokens,
     * allowing blocks to use SDK-defined color tokens for section backgrounds.
     */
    sdkConfig?: RuntimeSdkConfig | null;
    /**
     * Additional context data for content entry pages.
     * Used to pass occurrence context and content entry data to blocks.
     */
    dataContext?: {
        /** Occurrence context for event pages (from URL like /events/yoga/2025-01-15) */
        occurrenceContext?: OccurrenceContextData | null;
        /** Content entry data for template pages */
        contentEntry?: Record<string, unknown> | null;
    };
    wrapBlock?: (blockId: string, rendered: React.ReactNode) => React.ReactNode;
    registry?: Parameters<typeof PageRenderer>[0]['registry'];
    usePlaceholders?: boolean;
    /**
     * Custom components to override default block rendering.
     * Keys can be full block kind ("block.hero") or short form ("hero").
     *
     * This is SSR-safe - no context or hooks required.
     *
     * @example
     * ```tsx
     * <Page
     *   {...pageData}
     *   blockOverrides={{
     *     'hero': MyCustomHero,
     *     'block.testimonials': MyCustomTestimonials,
     *   }}
     * />
     * ```
     */
    blockOverrides?: BlockOverrides;
};
/**
 * Pure renderer for Riverbank CMS pages.
 *
 * This component expects all data to be provided via props.
 * For data fetching, use:
 * - Server-side: `await loadPage({ client, siteId, path })`
 * - Client-side: `usePage({ client, siteId, path })`
 *
 * @example Server-side (Next.js App Router)
 * ```tsx
 * import { createRiverbankClient } from '@riverbankcms/sdk';
 * import { loadPage, Page } from '@riverbankcms/sdk/rendering';
 *
 * const client = createRiverbankClient({ apiKey, baseUrl });
 *
 * export default async function PageRoute({ params }) {
 *   const pageData = await loadPage({
 *     client,
 *     siteId: 'site-id',
 *     path: `/${params.slug}`,
 *   });
 *
 *   return <Page {...pageData} />;
 * }
 * ```
 *
 * @example Client-side
 * ```tsx
 * import { createRiverbankClient } from '@riverbankcms/sdk';
 * import { usePage, Page } from '@riverbankcms/sdk/rendering';
 *
 * const client = createRiverbankClient({ apiKey, baseUrl });
 *
 * function MyPage({ path }) {
 *   const pageData = usePage({ client, siteId: 'site-id', path });
 *
 *   if (pageData.loading) return <LoadingState />;
 *   if (pageData.error) return <ErrorState error={pageData.error} />;
 *   if (!pageData.page) return <NotFound />;
 *
 *   return <Page {...pageData} />;
 * }
 * ```
 */
declare function Page({ page, theme, themeTokens: providedTokens, siteId, resolvedData, routeMap, wrapBlock, registry, usePlaceholders, blockOverrides, sdkConfig, dataContext, }: PageProps): react_jsx_runtime.JSX.Element;

/**
 * Client-side React hook to fetch page data.
 *
 * Use this in client components for dynamic page loading.
 */

type UsePageParams = {
    client: RiverbankClient;
    siteId: string;
    path: string;
    pageId?: string;
    /**
     * If true, fetches draft/unpublished content instead of published content.
     * This affects both the page structure and block data loaders.
     * Requires API key with site access.
     *
     * @default false
     */
    preview?: boolean;
};
type UsePageResult = {
    loading: true;
    error: null;
    page: null;
    theme: null;
    siteId: string;
    resolvedData: null;
    sdkConfig: null;
} | {
    loading: false;
    error: Error;
    page: null;
    theme: null;
    siteId: string;
    resolvedData: null;
    sdkConfig: null;
} | {
    loading: false;
    error: null;
    sdkConfig: RuntimeSdkConfig | null;
} & Omit<PageProps, 'registry' | 'wrapBlock' | 'usePlaceholders' | 'sdkConfig'>;
/**
 * Client-side React hook to fetch all data needed for <Page> component.
 *
 * Fetches site data, page data, and prefetches block data loaders.
 * Returns loading and error states for proper UI handling.
 *
 * IMPORTANT: The client object should be stable across renders to avoid
 * unnecessary re-fetches. Create it outside your component or use useMemo:
 *
 * ```tsx
 * // ✅ Good - stable reference
 * const client = useMemo(
 *   () => createRiverbankClient({ apiKey, baseUrl }),
 *   [apiKey, baseUrl]
 * );
 *
 * // ❌ Bad - new client on every render (causes infinite loops)
 * const client = createRiverbankClient({ apiKey, baseUrl });
 * ```
 *
 * @example Basic usage
 * ```tsx
 * import { createRiverbankClient } from '@riverbankcms/sdk';
 * import { usePage, Page } from '@riverbankcms/sdk/rendering';
 *
 * const client = createRiverbankClient({
 *   apiKey: process.env.NEXT_PUBLIC_RIVERBANK_API_KEY!,
 *   baseUrl: process.env.NEXT_PUBLIC_DASHBOARD_URL + '/api',
 * });
 *
 * function MyPage({ path }: { path: string }) {
 *   const pageData = usePage({ client, siteId: 'site-123', path });
 *
 *   if (pageData.loading) {
 *     return <div>Loading...</div>;
 *   }
 *
 *   if (pageData.error) {
 *     return <div>Error: {pageData.error.message}</div>;
 *   }
 *
 *   return <Page {...pageData} />;
 * }
 * ```
 *
 * @example With custom loading/error states
 * ```tsx
 * function MyPage({ path }: { path: string }) {
 *   const pageData = usePage({ client, siteId: 'site-123', path });
 *
 *   if (pageData.loading) {
 *     return <Skeleton />;
 *   }
 *
 *   if (pageData.error) {
 *     return (
 *       <ErrorBoundary
 *         error={pageData.error}
 *         onRetry={() => window.location.reload()}
 *       />
 *     );
 *   }
 *
 *   return <Page {...pageData} />;
 * }
 * ```
 */
declare function usePage(params: UsePageParams): UsePageResult;

export { type PageResponse as P, type RiverbankClient as R, type SiteResponse as S, type UsePageParams as U, type UsePageResult as a, type PageProps as b, type RiverbankClientConfig as c, Page as d, usePage as u };
